Запуск Python 3.7.3 на Mac и Windows, а также решение другой моей проблемы:
Невозможно найти субмодуль в пакете на одном ПК, но не на другом ПК
Я прочитал десяток постов, касающихся пакетов и модулей, таких как этот:
Может кто-нибудь объяснить __all__ на Python?
Однако я все еще получаю неожиданные результаты.
У меня есть структура пакета
pypkg/
__init__.py
src/
__init__.py
app.py
util/
__init__.py
util.py
src / app.py работает следующим образом
# app.py
from pprint import pprint
import sys
pprint(sys.path, indent=4)
from util import *
def main():
print('this is app.')
util.func()
pprint(sys.path, indent=4)
if __name__ == '__main__':
main()
util / util.py выглядит следующим образом
# util.py
def func():
print('this is func from util.')
И я ожидаю, что, сидя под корнем проекта, т.е. /path/to/pypkg/
, я смогу позвонить:
python src/app.py
И запустить его без проблем.
Однако, это дает мне:
ModuleNotFoundError: No module named 'util'
Затем я переключаюсь на работу:
python -m src.app
На этот раз я получаю:
NameError: global name 'util' is not defined
Наконец, я вручную добавляю следующее к util/__init__.py
:
__all__ = ['util']
На этот раз все в порядке.
Мои предположения из опыта:
- Зависимость пакета будет работать только при запуске Python с опцией
-m
.
- Мое первоначальное впечатление, что
__init__.py
может быть пустым, является заблуждением. Если бы я использовал from <package> import *
, то __init__.py
ДОЛЖЕН определить __all__
.
- Текущий рабочий каталог имеет значение при использовании системы пакетов.
Мой вопрос: все мои предположения верны?
Если все мои предположения верны, то было бы неудобно использовать систему пакетов с базой кода, которая смешивает код приложения и код зависимости, где в общем случае вы хотите перейти в командную строку, где бы вы ни находились, и просто вызвать python random/relative/path/to/script.py
. Но пакеты с этой парадигмой плохо работают.
Теперь мои следующие вопросы:
Должен ли я использовать пакет таким образом? Лучше всего придерживаться старого доброго sys.path
взлома, если сам «пакет» содержит код приложения?