Search code examples
pythonpython-3.xevalpython-import

exec function: import unknown in class definition


I want to use Python files to configure a program. The files will be read via exec. Part of the configuration are class definitions:

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)

Now, when running main.py I'll have the problem that outside of the class definition the imported module is known but inside it is not. Why and is there a workaround?


Solution

  • According to exec's documentation,

    If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.

    So your config.py code is equivalent to

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

    This is a problem because, according to Resolution of Names,

    The scope of names defined in a class block is limited to the class block[.]

    col is defined in the class block of the implicit SomeClass. This variable's scope is limited to that class block only; even blocks inside that block, such as class Foo:, can't access it.

    One possible solution is to pass the same object for globals and locals so that your code is not executed as if it were embedded in a class definition.

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