Python使用compile+exec执行赋值代码在函数内报NameError全局运行正常
Python exec函数在函数作用域与全局作用域的行为差异问题解答
成因
Python函数的局部变量在代码编译阶段就会确定存储位置,exec动态执行代码新增的变量不会被纳入函数的静态局部变量列表:
- 全局作用域下执行exec时,代码中定义的变量会直接写入全局命名空间,后续访问可以正常找到对应变量。
- 函数作用域下默认执行exec时,变量会写入函数的局部命名空间字典,但解释器访问局部变量时不会扫描这个动态字典,只会去查找编译阶段确定的静态局部变量,因此找不到动态生成的
n,抛出NameError。
解决方案
方案1:显式传入自定义命名空间,主动获取变量
最安全的方案,不会污染全局或局部命名空间:
def main(): c = compile("n = int(input('>>>'))", "", "single") # 用自定义字典存储exec执行生成的变量 namespace = {} exec(c, namespace) # 从自定义字典中取出变量 n = namespace['n'] print(n)
方案2:指定exec写入全局命名空间
适合需要把变量设为全局的场景:
def main(): c = compile("n = int(input('>>>'))", "", "single") # 传入globals()指定将变量写入全局命名空间 exec(c, globals()) print(n)
方案3:直接从locals()字典读取动态变量
不需要额外定义字典时可使用:
def main(): c = compile("n = int(input('>>>'))", "", "single") exec(c) # 直接从局部命名空间字典中读取动态生成的变量 print(locals()['n'])
内容的提问来源于stack exchange,提问作者Waylan Punch
相关产品推荐
相关产品推荐

