Почему я получаю «NameError: имя не определено» с exec ()? - PullRequest
0 голосов
/ 23 февраля 2019

Когда я пытаюсь этот код в консоли (в PyCharm):

exec("import random")
exec("def f():\n\treturn random.randint(0, 10), random.randint(0, 10)")
locals()['f']()

, он работает нормально.Но когда я пытаюсь сделать то же самое в моей программе, это не работает, и я получаю исключение

NameError: name 'random' is not defined.

. Я обнаружил, что этот код не вызывает ошибок:

exec("import random", globals(), globals())
exec("def f():\n\treturn random.randint(0, 10), random.randint(0, 10)", globals(), globals())
globals()['f']()

Но я не могу понять, почему.

Что происходит?

1 Ответ

0 голосов
/ 24 февраля 2019

Вы не делаете "точно то же самое" в вашей программе.Точный код, дословно скопированный в файл и выполняемый как скрипт Python, работает просто отлично (хотя и без видимого результата).

Я думаю, что вы действительно могли бы делать что-то вроде этого:

def import_stuff():
    exec("import random")

def do_stuff():
    import_stuff()
    exec("def f():\n\treturn random.randint(0, 10), random.randint(0, 10)")
    locals()['f']()

do_stuff()

Приведенный выше код действительно приводит к исключению NameError, указанному в вашем вопросе, потому что (цитируя документы ),

Во всех случаях, еслинеобязательные части опущены, код выполняется в текущей области.

Поскольку приведенный выше код импортирует random в локальную область import_stuff(), он не виден для do_stuff().

Фактически, приведенный выше код по своему поведению идентичен следующему:

def import_stuff():
    import random

def do_stuff():
    import_stuff()
    def f():
        return random.randint(0, 10), random.randint(0, 10)
    f()

do_stuff()

..., который также не работает по той же причине.

Предполагается, что это действительно происходитв вашем реальном коде будет работать версия, измененная, как и в вашем вопросе, с добавлением globals(), globals() аргументов к exec(), потому что тогда вы явно импортируете random в глобальную область видимости, где все это видят.

...