Выполнить установленный пакет Python как script?

Есть ли способ включить пакет в качестве script? Например:

[~]# easy_install /path/to/foo.egg
...
[~]# python -m foo --name World
Hello World

Я попытался создать файл __main__.py внутри моего пакета, но он не выполняется (я использую Python 2.6). Возникает следующая ошибка:

foo is a package and cannot be directly executed

Структура моего пакета выглядит следующим образом:

foo/
  setup.py
  foo/
    __init__.py
    __main__.py

Запуск python -m foo.__main__ --name World работает так, как ожидалось, но я предпочел бы прежний способ исполнения. Возможно ли это?

Ответ 1

Это регрессия в Python 2.6. См. issue2571:

Возможность выполнять пакеты никогда не планировалась, так как ломает импорт различными путями. На самом деле это была ошибка в 2.5, что это было разрешено вообще, поэтому 2.6 не только снова отключил его, но также добавил тест, чтобы убедиться, что он отключен (2.4 правильно отклонил его с помощью ImportError, как это делает 2.6).

У вас есть несколько вариантов, вы можете либо всегда запускать его, указав main:

$ python -m module.__main__

Или вы можете написать оболочку script, которая обнаруживает версию python, а затем выполняет ее в другом стиле.

Или вы можете выполнить код в командной строке, который будет импортировать, а затем запустить модуль, а затем, возможно, поместить его в оболочку script:

$ python -c "import module; module.main()"

В моих собственных проектах с командной строкой у меня есть и оболочка script, которая ловит ошибки (python не устанавливается и т.д.), но оболочка script также выполняет код импорта и обнаруживает, были ли необходимые модули (с полезной ссылкой или установочным текстом).

Ответ 2

Я думаю, что это может быть ограничение Python 2.6. Я протестировал его, и выполнение пакета (либо в ., либо установленном из яйца с easy_install) с опцией -m работает отлично в 2.7, но не в 2.6. Например, в моей системе (Ubuntu) с тестовым пакетом с именем pkg_exec в текущем каталоге и где __main__.py просто печатает sys.argv:

[email protected]:~/tmp/pkg_exec$ python2.6 -m pkg_exec
/usr/bin/python2.6: pkg_exec is a package and cannot be directly executed
[email protected]:~/tmp/pkg_exec$ python2.7 -m pkg_exec
['/home/xx/tmp/pkg_exec/pkg_exec/__main__.py']

Кроме того, согласно 2.7 docs:

Изменено в версии 2.7: укажите имя пакета для запуска подмодуля __main__.

Ответ 3

пока пакет находится на пути python, добавьте в конец script.

if __name__ == "__main__":
     call_script()
$ python -m module_name  

запустит модуль, например,

python -m random