Вы не делаете "точно то же самое" в вашей программе.Точный код, дословно скопированный в файл и выполняемый как скрипт 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
в глобальную область видимости, где все это видят.