2016-06-25 3 views
2

Дано:Почему запуск подмодуля (python -m a.c) также импортирует содержащий модуль?

tree

~/dir                   
▶ tree 
. 
├── a 
│   ├── __init__.py 
│   ├── c.py 
└── b.py 

1 directory, 3 files 

*.py файлы

~/dir                   
▶ tail -n +1 **/*.py             
==> a/__init__.py <== 
print(__name__) 
import a.c 

==> a/c.py <== 
print(__name__) 

==> b.py <== 
print(__name__) 
import a 

I/O

~/dir                   
▶ python3 -m a.c 
a 
a.c 
__main__ 

Модуль a.c не имеет зависимостей от модуля a. Итак, почему Python запускает модуль a, как если бы он импортировал его? Для меня это удивительное поведение. Я не ожидал, что запуск скрипта без импорта приведет к тому, что сам скрипт будет импортироваться и оцениваться дважды. Разве это не опасно для скриптов, которые не используют защиту if __name__ == "__main__"?

Какое оправдание этому поведению? Почему Python должен оценивать содержащийся модуль при запуске его подмодуля?

ответ

1

Модуль a.c не имеет зависимости от модуля a. Итак, почему Python запустить модуль А, как если бы оно было импортировать его

From the documentation:

Импорт parent.one будет беспрекословно выполнять parent/__init__.py и parent/one/__init__.py. Последующий импорт parent.two или parent.three будет выполнять parent/two/__init__.py и parent/three/__init__.py соответственно.


Для меня это удивительно поведение. Я не ожидал, что запуск скрипта без импорта приведет к тому, что сам скрипт будет импортироваться и оцениваться дважды.

Нет, это не удивительно. Подумайте об этом: все объекты, выставленные пакетом a, в вашем примере контролируются a/__init__.py. Теперь интерпретатор должен оценить a/__init__.py, чтобы узнать, существует ли вообще a.c. И в этом процессе выполняется оператор печати. Кроме того, ни один модуль не импортируется дважды. Он импортируется только один раз - хотя вы можете технически писать операции импорта несколько раз.

+0

Я не думал об объектах, выставленных '__init __. Py'. –

0

Модуль a.c не имеет зависимостей от модуля

Вы путаете пакет с модулем.

`a` is a package 
`c` is a module within package `a` 

Существует зависимость: a.c является членом пакета a.

Вопросы по этому поводу являются общими

What's the difference between a Python module and a Python package?

Module vs. Package?

Так почему же модуль Python Выполнить, как если бы это были его импорта? Для меня это удивительное поведение

При импорте модуля a.c, Python процессов пакет a, который включает в себя выполнение кода в a/__init__.py, а затем модуль c.py

Q: Почему?

A: Потому что это то, что говорит язык. :) (Я знаю, это на самом деле не , почему вы имели в виду.)

В: Почему? Как и в том, «зачем ему это делать, что хорошего может быть?»

A: Уровень инициализации пакета может сделать что-то полезное.

Пакет init может предоставлять вещи, и члены могут рассчитывать на выполнение пакета перед запуском модуля-члена.

Вы поместили c в пакет a по причине.

Люди могут использовать пакеты просто для структурной организации. Если у вас есть опыт Java, вы можете увидеть точки, как только вы организуете занятия. Если вы используете только a, оставьте __init__.py пустым, и все будет так, как вы ожидаете.

Но пакет a/__init__.py допускает другие способности. Это требует правильного использования, но доступно, когда вам это нужно.

Не было ли это опасным для сценариев, которые не используют защиту if __name__ == "__main__":?

Да, вам нужно четко знать, какие сценарии предназначены для запуска (например, python b.py) и какие модули предназначены для контейнеров для классов и функций.

В общем, модули не предназначены для выполнения как автономные скрипты. Общим исключением является тестирование и разработка. Затем вы будете регулярно видеть биты тестового кода

if __name__ == "__main__": 
    x = somefunction() 
    print(x) 
    a = SomeClass() 
    y = a.foo() 
    print(y) 
Смежные вопросы