вызов execfile () в пользовательском пространстве имен выполняет код в пространстве имен '__builtin__' - PullRequest
4 голосов
/ 02 апреля 2009

Когда я вызываю execfile без передачи аргументов globals или localals, он создает объекты в текущем пространстве имен, но если я вызываю execfile и указываю dict для globals (и / или locals), он создает объекты в пространстве имен __builtin__.

Возьмите следующий пример:

# exec.py
def myfunc():
    print 'myfunc created in %s namespace' % __name__

exec.py execfile'd из main.py следующим образом.

# main.py
print 'execfile in global namespace:'
execfile('exec.py')
myfunc()
print    

print 'execfile in custom namespace:'
d = {}
execfile('exec.py', d)
d['myfunc']()

когда я запускаю main.py из командной строки, я получаю следующий вывод.

execfile in global namespace:
myfunc created in __main__ namespace

execfile in custom namespace:
myfunc created in __builtin__ namespace

Почему он запускается в __builtin__ пространстве имен во втором случае?

Кроме того, если я затем пытаюсь запустить myfunc из __builtins__, я получаю AttributeError. (Это то, что, я надеюсь, произойдет, но тогда почему __name__ установлено на __builtin__?)

>>> __builtins__.myfunc()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'module' object has no attribute 'myfunc'

Может кто-нибудь объяснить это поведение? Спасибо

Ответы [ 3 ]

4 голосов
/ 02 апреля 2009

Прежде всего, __name__ не является пространством имен - это ссылка на имя модуля, к которому он принадлежит, то есть: somemod.py -> somemod.__name__ == 'somemod' Исключением является то, что если вы запускаете модуль как исполняемый файл из командной строки, то __name__ - это __main __.

в вашем примере есть счастливое совпадение, что ваш модуль, запускаемый как main, также называется main.

Execfile выполняет содержимое модуля БЕЗ импорта его как модуля. Таким образом, __name__ не устанавливается, потому что это не модуль - это просто исполняемая последовательность кода.

1 голос
/ 03 апреля 2009

Кроме того, я предпочитаю использовать __import__() вместо execfile:

module = __import__(module_name)
value = module.__dict__[function_name](arguments)

Это также хорошо работает при добавлении в PYTHONPATH, так что модули в других каталогах могут быть импортированы:

sys.path.insert(position, directory)
1 голос
/ 02 апреля 2009

Функция execfile похожа на инструкцию exec. Если вы посмотрите документацию для exec , вы увидите следующий параграф, объясняющий поведение.

В качестве побочного эффекта реализация может вставить дополнительные ключи в указанные словари, помимо тех, которые соответствуют именам переменных, установленным исполняемым кодом. Например, текущая реализация может добавить ссылку на словарь встроенного модуля __builtin__ под ключом __builtins__ (!).

Редактировать: Теперь я вижу, что мой ответ относится к одной возможной интерпретации названия вопроса. Мой ответ не относится к фактическому заданному вопросу.

...