exec函数:在类定义中导入未知

时间:2019-06-04 12:24:52

标签: python python-3.x eval python-import

我想使用Python文件配置程序。将通过exec读取文件。配置的一部分是类定义:

config.py

import collections as col  # module alias does not matter

a = col.defaultdict()  # works as expected

class Foo:
    b = col.defaultdict()  # causes NameError: name 'col' is not defined

main.py

CONFIG = {}

with open('config.py') as f:
    exec(f.read(), None, CONFIG)

现在,当运行 main.py 时,我会遇到这样的问题:在类定义之外,导入的模块是已知的,但在模块内部则未知。为什么并且有解决方法?

1 个答案:

答案 0 :(得分:3)

根据exec's documentation

  

如果exec获得了两个单独的对象(全局对象和局部对象),则代码将像嵌入在类定义中一样执行。

因此您的config.py代码等同于

class SomeClass:
    import collections as col
    a = col.defaultdict()
    class Foo:
        b = col.defaultdict()

这是一个问题,因为根据Resolution of Names

  

在类块中定义的名称范围仅限于类块[。]

col在隐式SomeClass的类块中定义。该变量的范围仅限于该类块;即使该块中的块(例如class Foo:)也无法访问它。

一种可能的解决方案是为globalslocals传递相同的对象,这样就不会像嵌入类定义中那样执行代码。 >

exec(f.read(), CONFIG, CONFIG)