Home > Net >  NameError: name is 'x' not defined when run a sample template system in python
NameError: name is 'x' not defined when run a sample template system in python

Time:11-05

I am trying to use the following code for a template system, which comes "Beginning Python: From Novice to Professional", 3Ed by Magnus Lie Hetland:

# template.py

import fileinput, re

field_pat = re.compile(r'\[(. ?)\]')

scope = {}
def replacement(match):
    code = match.group(1)
    try:
        return str(eval(code, scope))
    except SyntaxError:
        return ''

lines = []
for line in fileinput.input():
    lines.append(line)
text = ''.join(lines)

print(field_pat.sub(replacement, text))

The book describes this text file, named number.txt:

[x = 2]
[y = 3]
The sum of [x] and [y] is [x   y].

When I tried to replace x & y with numbers using the template,

> python template.py number.txt

I was expecting to see The sum of 2 and 3 is 5. Instead, however, I get this error message:

Traceback (most recent call last):
  File "D:\Python\template.py", line 18, in <module>
    print(field_pat.sub(replacement, text))
  File "D:\Python\template.py", line 9, in replacement
    return str(eval(code, scope))
  File "<string>", line 1, in <module>
NameError: name 'x' is not defined

Why does this occur? I am using Python 3.10.0, if it matters.

CodePudding user response:

eval() only works on expressions, but assignment is a statement in Python. exec() works on statements.

So what you could do is try parsing an expression, then fall back to a statement.

def replacement(match):
    code = match.group(1)
    try:
        return str(eval(code, scope))  # Try evaluating expression
    except SyntaxError:
        exec(code, scope)  # Execute statement
        return ''
>>> text = '[x = 2][y = 3]The sum of [x] and [y] is [x   y].'
>>> field_pat.sub(replacement, text)
'The sum of 2 and 3 is 5.'

To be clear, any assignments will be made to scope, which is acting as the global scope.


By the way, if your input is untrusted, eval() is dangerous, and by extension, so is exec(). I hope you're only using this code for learning purposes.

  • Related