Python:在'exec'环境中奇怪的"NameError:name ...未定义"

gin*_*ger 7 python python-3.x

我有信心至少对Python的范围系统有一些基本的了解.现在我收到一个错误,遗憾的是到目前为止我甚至无法为复制编写好的代码片段.我尝试在一个新的小项目中重现它,但一切都按照我的预期运行: - /

我只能描述我的所作所为,并希望有人能够检测出一种模式并告诉我这里可能出现的问题.

起初有一个python文件x.py实现了一个类X.

在其他一些python文件中,有以下字符串:

code="""
...
from x import X
...
class Y(X): # does not crash here, ...
    def __init__(self):
        X.__init__(self) # ... but here
        ...
foo=Y()
"""
Run Code Online (Sandbox Code Playgroud)

您可以假设python能够找到该x模块.在某个地方,我尝试执行:

exec(code, globals(), locals())
Run Code Online (Sandbox Code Playgroud)

现在我得到了NameError.它告诉我,X当它试图调用它的构造函数时没有定义.它显然定义在上面几行.

如果我通过Y.__init__添加from x import X为第一行进行修改,则可以正常工作.但为什么我要在那里再次导入呢?

如前所述,实际代码更复杂,并且做了更多事情.在一个不幸的情况下,我的帖子甚至没有显示实际导致问题的部分.但也许你有一些一般的想法,如何才能得到这样的行为.

aba*_*ert 7

这只是一个猜测,因为您没有给我们展示足够的代码,而您给我们展示的内容实际上并没有重现问题,但是……

如果您在exec函数内部执行此操作,则locals()globals()将有所不同。在这种情况下,代码将像在类定义中一样被执行。因此,就像您这样做:

class _:
    from x import X
    class Y(X): # does not crash here, ...
        def __init__(self):
            X.__init__(self) # ... but here
    foo=Y()
del _
Run Code Online (Sandbox Code Playgroud)

(我以前认为您必须在Y()之外执行类似的操作exec,但user2357112的回答使我确信这不是必需的。)

如果这是您的问题,您可以通过致电exec(code, globals(), globals())或来解决exec(code, locals(), locals())。(当然,哪一个合适,取决于您实际上要尝试执行的操作,而您没有告诉我们。)


use*_*ica 7

exec文档:

如果exec获得两个单独的对象作为全局变量和局部变量,则代码将被执行,就像它嵌入在类定义中一样.

这有很好的理由,我不会在这里讨论.

类定义中定义的函数不会查看变量分辨率的类定义的范围.当你exec的时候code,它实际上是这样执行的:

class Dummy:
    from x import X
    ...
    class Y(X):
        def __init__(self):
            X.__init__(self)
            ...
    foo=Y()
Run Code Online (Sandbox Code Playgroud)

这意味着这个功能:

def __init__(self):
    X.__init__(self)
Run Code Online (Sandbox Code Playgroud)

没有看到这个变量:

from x import X
Run Code Online (Sandbox Code Playgroud)

即使这一点:

class Y(X):
Run Code Online (Sandbox Code Playgroud)

确实看到了.