python - NameError:在 python 中运行示例模板系统时未定义名称为“x”
问题描述
我正在尝试将以下代码用于模板系统,该系统来自 Magnus Lie Hetland 的第 3 版“Beginning Python: From Novice to Professional”:
# 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))
这本书描述了这个文本文件,名为number.txt
:
[x = 2]
[y = 3]
The sum of [x] and [y] is [x + y].
当我尝试使用模板将 x & y 替换为数字时,
> python template.py number.txt
我期待看到The sum of 2 and 3 is 5.
相反,但是,我收到此错误消息:
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
为什么会出现这种情况?如果重要的话,我正在使用 Python 3.10.0。
解决方案
eval()
仅适用于表达式,但赋值是 Python 中的语句。exec()
适用于语句。
所以你可以做的是尝试解析一个表达式,然后回退到一个语句。
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.'
需要明确的是,任何分配都将被分配给scope
充当全局范围的 。
顺便说一句,如果您的输入不受信任,eval()
是危险的,并且通过扩展,也是如此exec()
。我希望您仅将此代码用于学习目的。