记录一个很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.