exec()在不同namespace执行结果的区别

记录一个很tricky的问题,下面这段code在执行'func1'时会出现NameError: name 'List' is not defined,但执行'func2'时一切正常。

import types

content = """
from typing import List

class GeneratedData:
  qna: List

"""


def func1(content):
    exec(content)
    _locals = {k: v for k, v in locals().items()}
    print(len(_locals))


def func2(content):
    m = types.ModuleType("promptflow.dummy")
    exec(content, m.__dict__)
    _locals = m.__dict__
    print(len(_locals))

原因是exec(content)执行的时候import statement都直接修改了locals, 导致后面的code执行的时候在globals里找不到import的东西,但是如果给一个module的话相当于在一个独立的namespace里运行,就不会出现找不到的问题。附上问copilot chat得到的回复:

The difference between the two functions is that func2 creates a new module using types.ModuleType and executes the code within that module's namespace, while func1 executes the code in the current namespace.

When you execute code in the current namespace, any imports or definitions made in that code will affect the current namespace. So if the code being executed contains an import statement that is not defined in the current namespace, you will get an error.

On the other hand, when you execute code in a new module's namespace, any imports or definitions made in that code will only affect that module's namespace. So if the code being executed contains an import statement that is not defined in the current namespace, it will not raise an error as long as the import is defined in the imported module.

In summary, func2 works because it creates a new module and executes the code within that module's namespace, while func1 executes the code in the current namespace, which can cause import errors.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值