python, global name is not defined

Makc500

Есть некая программа (1.py из которой, помимо всего прочего, напрямую запускается другая:

...
execfile('2.py')
...

2.py имеет примерно такой вид:

def A:
...

def B:
...
A
...

#main
....
B
...


При запуске 1.py всплывает ошибка:
NameError: global name 'A' is not defined
и указывает на соответствующее место в функции B
Если просто запустить 2.py в интерпретаторе, то всё работает
Why is this?

Dasar

при шаманских ошибках бывает, что просто "не туда смотришь". запускаешь в одной папке, а смотришь в другой, и т.д.
и помогает только побуквенно проверить все допущения
проверь из какой папки у тебя действительно 2.py берется.
execfile из текущей диры берет? может 1.py меняет текущую диру?

Makc500

нет, 2.py запускается, так как прогоняется его main, и B до того места, как вызывается A.
грубо говоря B видится, а A - нет, хотя определено раньше B
Более того, если прогнать хотя бы один раз 2.py в интерпретаторе напрямую, то он "запоминается" и 1.py работает нормально.

boikodima1

а если добавить вначале B "global A" ошибка остается?
PS. это явно зависит либо от версии питона, либо от того что в ..., т.к. у меня все ок работает

Makc500

python 2.6.2
У меня тоже раньше всё работало, но после "модернизации" перестало. Хотя не припомню, чтобы менял что-то связанное с этим.
Но по факту должна же работать такая схема. Как ее можно "дебажить"?

tipnote

Точно полная схема? Нигде нет импорта 2.py?
В общем, нужен полноценный код.
ЗЫ Ну а если занудничать, то не надо так делать. Писать импорт-тайм код, а потом экзекать его в чужом контексте

Commandor

Файл 1.py так должен выглядеть, чтобы воспроизводилось:

def x:
execfile('2.py')
x

У execfile-а еще два параметра есть: globals и locals. Чтобы указанный код работал как хочется можно в качестве globals и locals передать один и тот же dict.

Makc500

Реально, так работает:
1.py:

execfile('2.py')

а так нет:
1.py:

def x:
  execfile('2.py')
x

А можно про это поподробнее:
>Чтобы указанный код работал как хочется можно в качестве globals и locals передать один и тот же dict.

Commandor

А можно про это поподробнее:
Ну например так:

def x:
env = {}
execfile('2.py',env, env)
# или так:
# If the locals dictionary is omitted it defaults to the globals dictionary.
execfile('2.py',env)
x

Фича в том, что если явно не указывать параметры, то для скрипта, вызванного через execfile, окружение (globals + locals) выставляется равным окружению в котором выполнилась функция execfile. Внутри функции globals и locals различные объекты, при этом locals только для чтения - у кода в файле 2.py возникают некоторые проблемы с добавлением новых объектов в область видимости.
Вообщем это несколько мутно и я эту проблему знаю, но не до конца понимаю, т.к. сталкиваться с execfile-ом особо не приходилось.
Оставить комментарий
Имя или ник:
Комментарий: