背景描述:
在项目中,需要动态编辑python脚本,动态执行。exec方法可以动态的执行脚本代码
遇到的问题:
在脚本代码中,定义了多个方法,多个方法存在相互调用关系。将脚本放在exec方法中执行时,被嵌套执行的方法编译报错,错误提示:NameError: name 'b' is not defined
代码实例如下:
code = '''
def b(x):
print(x)
def a(x):
b(x)
a(x)
# '''
params = {
'x': 1
}
exec(code, None, params)
问题排查:
在方法a中,使用globals()和locals()查看全局和局部定义的内容,代码如下:
code = '''
def b(x):
print(x)
def a(x):
# print()
print('*'*20)
print(globals())
print('*'*20)
print(locals())
b(x)
a(x)
# '''
params = {
'x': 1
}
exec(code, None, params)
// globals
{
'__name__': '__main__',
'__doc__': None,
'__package__': None,
'__loader__': < _frozen_importlib_external.SourceFileLoader object at 0x108f7aca0 > ,
'__spec__': None,
'__annotations__': {},
'__builtins__': < module 'builtins' (built - in ) > ,
'__file__': '/Users/andrew/PycharmProject/demos/exec_demo.py',
'__cached__': None,
'code': "\ndef b(x):\n print(x)\n \ndef a(x):\n # print()\n print('*'*20)\n print(globals())\n print('*'*20)\n print(locals())\n b(x)\n \na(x)\n# ",
'params': {
'x': 1,
'b': < function b at 0x108fc51f0 > ,
'a': < function a at 0x109062d30 >
}
}
// locals
{
'x': 1
}
发现方法b并没有被注册在全局上下文中。编译器在解释代码时,并不知道方法是否被嵌套使用,因此从全局获取。
解决思路:
将b注册在全局中,代码如下所示:
code = '''
def b(x):
print(x)
def a(x):
b(x)
a(x)
# '''
params = {
'x': 1
}
exec(code, params, None)
欢迎大家留言交流~