Intro
分析时,常常拼接字符串,作为代码执行。此时会调用exec方法,在命令行或者jupyter中执行,exec执行的变量,在外部可以引用。而嵌套在函数内部时,则不能引用。看几个例子:
exec_str ="""
a = 1
"""
exec(exec_str)
print(f'a={a}')
a=1
def exe_f():
exec_str = f"""
fun_y = 1
print(f"exec_str:fun_y=",fun_y)
"""
exec(exec_str)
print(f"exe_f:fun_y=",fun_y)
exe_f()
exec_str:fun_y= 1
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_24724\1254702322.py in <module>
7 print(f"exe_f:fun_y=",fun_y)
8
----> 9 exe_f()
~\AppData\Local\Temp\ipykernel_24724\1254702322.py in exe_f()
5 """
6 exec(exec_str)
----> 7 print(f"exe_f:fun_y=",fun_y)
8
9 exe_f()
NameError: name 'fun_y' is not defined
原理见ref[1]
,简言之,exec时,变量fun_y并没有注册到局部空间,因此引用时获取失败。
解法
有几种方法,依次看下
把exec执行结果保存到globals()
def exe_f():
exec_str = f"""
fun_y = 1
print(f"exec_str:fun_y=",fun_y)
"""
exec(exec_str,globals())
print(f"exe_f:fun_y=",fun_y)
exe_f()
print(f"globals:fun_y=",fun_y)
exec_str:fun_y= 1
exe_f:fun_y= 1
globals:fun_y= 1
该方法可能会导致全局变量被污染
自定义字典
def exe_f():
self_dict = {}
exec_str = f"""
fun_y1 = 1
print(f"exec_str:fun_y1=",fun_y1)
"""
exec(exec_str,globals(),self_dict)
print(f"exe_f:fun_y=",self_dict['fun_y1'])
exe_f()
var_name = 'fun_y1'
print(f'locals() {var_name}:{locals().get(var_name, None)}')
exec_str:fun_y1= 1
exe_f:fun_y= 1
locals() fun_y1:None
此时不会污染全局变量
Ref
2022-11-27 于南京市江宁区