функция exec: импорт неизвестен в определении класса - PullRequest
1 голос
/ 04 июня 2019

Я хочу использовать файлы 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 Ответ

3 голосов
/ 04 июня 2019

Согласно документации exec ,

Если exec получит два отдельных объекта как глобальные и локальные, код будет выполнен так, как если бы он был встроен в определение класса.

Итак, ваш код config.py эквивалентен

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

Это проблема, потому что, согласно Разрешение имен ,

Область имен, определенных в блоке класса, ограничена блоком класса [.]

col определена в блоке класса неявного SomeClass.Область действия этой переменной ограничена только этим блоком класса;даже блоки внутри этого блока, такие как class Foo:, не могут получить к нему доступ.

Одно из возможных решений - передать один и тот же объект для globals и locals, чтобы ваш код не был выполняется так, как если бы он был встроен в определение класса.

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