В Python почему не работает импорт в exec в функции?

Я могу поместить оператор импорта в строку, выполнить его, и он работает (печатает случайную цифру):

code = """
import random
def f():
    print random.randint(0,9)
"""

def f():
    pass

exec code
f()

Теперь, если я поставлю exec code а также f() в своей собственной функции и вызвать его, это не работает.

def test():
    exec code
    f()

test()

Это говорит NameError: global name 'random' is not defined, Есть идеи, что происходит? Спасибо

3 ответа

Решение

Как насчет этого:

def test():
    exec (code, globals())
    f()

Здесь происходит то, что модуль random импортируется как локальная переменная в тесте. Попробуй это

def test():
    exec code
    print globals()
    print locals()
    f()

распечатает

{'code': '\nimport random\ndef f():\n    print random.randint(0,9)\n', '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'test': <function test at 0x02958BF0>, '__name__': '__main__', '__doc__': None}
{'random': <module 'random' from 'C:\Python27\lib\random.pyc'>, 'f': <function f at 0x0295A070>}

Причина f не вижу random в том, что f не является вложенной функцией внутри test- если вы сделали это:

def test():
    import random
    def f():
        print random.randint(0,9)
    f()

это будет работать. Однако вложенные функции требуют, чтобы внешняя функция содержала определение внутренней функции при компиляции внешней функции - это потому, что вам нужно установить переменные ячейки для хранения переменных, которые совместно используются двумя (внешними и внутренними) функциями.

Чтобы случайно попасть в глобальное пространство имен, вы просто должны сделать что-то вроде этого

exec code in globals(),globals()

Аргументы exec после in Ключевое слово - это глобальное и локальное пространства имен, в которых выполняется код (и, следовательно, где хранится имя, определенное в коде exec'd).

Укажите, что вы хотите глобальный random модуль

code = """
import random
def f():
  global random
  print random.randint(0,9)
"""

Проблема в том, что вы импортируете random модуль в область вашей функции, а не глобальную область.

Другие вопросы по тегам