Выполнение кода Python с параметром -m или без
Используйте -m
флаг.
Результаты почти такие же, когда у вас есть скрипт, но когда вы разрабатываете пакет без -m
флага, нет никакого способа заставить импорт работать правильно, если вы хотите запустить подпакет или модуль в пакете в качестве основной записи. укажите на вашу программу (и поверьте, я пробовал.)
Документы
Как и в документации по флагу -m :
Найдите в sys.path названный модуль и выполните его содержимое как __main__
модуль.
и
Как и в случае с параметром -c, текущий каталог будет добавлен в начало sys.path.
так
python -m pdb
примерно эквивалентен
python /usr/lib/python3.5/pdb.py
(при условии, что в вашем текущем каталоге нет пакета или скрипта с именем pdb.py)
Пояснение:
Поведение сделано «намеренно подобным» сценариям.
Многие стандартные библиотечные модули содержат код, который вызывается при их выполнении как сценарий. Примером может служить модуль timeit:
Некоторый код Python предназначен для запуска как модуля: (я думаю, что этот пример лучше, чем пример документа с параметром командной строки)
$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop
$ python -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 3: 33.4 usec per loop
$ python -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 3: 25.2 usec per loop
И из примечаний к выпуску для Python 2.4 :
Параметр командной строки -m - python -m modulename найдет модуль в стандартной библиотеке и вызовет его. Например, python -m pdb
эквивалентноpython /usr/lib/python2.4/pdb.py
Дополнительный вопрос
Кроме того, в Essential Reference Дэвида Бизли это объясняется следующим образом: «Параметр -m запускает библиотечный модуль как сценарий, который выполняется внутри __main__
модуля до выполнения основного сценария».
Это означает, что любой модуль, который вы можете найти с помощью оператора импорта, может быть запущен как точка входа в программу - если у него есть блок кода, обычно ближе к концу, с if __name__ == '__main__':
.
-m
без добавления текущего каталога в путь:
Комментарий здесь в другом месте гласит:
То, что опция -m также добавляет текущий каталог в sys.path, очевидно, является проблемой безопасности (см. Атака с предварительной загрузкой). Это поведение аналогично порядку поиска в библиотеках в Windows (до недавнего времени, когда он был усилен). Жалко, что Python не следует тенденции и не предлагает простого способа отключить добавление. к sys.path
Что ж, это демонстрирует возможную проблему - (в Windows удалите кавычки):
echo "import sys; print(sys.version)" > pdb.py
python -m pdb
3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]
Используйте -I
флаг, чтобы заблокировать это для производственных сред (новое в версии 3.4):
python -Im pdb
usage: pdb.py [-c command] ... pyfile [arg] ...
etc...
из документов :
-I
Запустите Python в изолированном режиме. Это также подразумевает -E и -s. В изолированном режиме sys.path не содержит ни каталога сценария, ни каталога пакетов сайта пользователя. Все переменные среды PYTHON * также игнорируются. Могут быть наложены дополнительные ограничения, чтобы предотвратить внедрение вредоносного кода пользователем.
Что __package__
делать?
Это позволяет явный относительный импорт, что не особенно важно для этого вопроса - см. Этот ответ здесь: Какова цель атрибута «__package__» в Python?
PYTHONPATH=test python -m foo.bar
? Не могли бы вы объяснить это подробнее?