首页 > 解决方案 > 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。

标签: pythonpython-3.x

解决方案


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()。我希望您仅将此代码用于学习目的。


推荐阅读