Создание исполняемого файла python с помощью setuptools

у меня есть небольшое приложение python, которое я хотел бы сделать загружаемым / устанавливаемым исполняемым файлом для UNIX-подобных систем. У меня сложилось впечатление, что setuptools-лучший способ сделать это, но почему-то это не кажется общей задачей.

моя структура каталогов выглядит так:

myappname/
|-- setup.py
|-- myappname/
|   |-- __init__.py
|   |-- myappname.py
|   |-- src/
|      |-- __init__.py
|      |-- mainclassfile.py
|      |-- morepython/
|         |-- __init__.py
|         |-- extrapython1.py
|         |-- extrapython2.py

файл, который содержит if __name__ == "__main__": is myappname.py - ... Этот файл имеет строку вверху,import src.mainclassfile.

когда это скачанный, я хотел бы, чтобы пользователь мог сделать что-то вроде:

$ python setup.py build
$ python setup.py install

и тогда это будет установленный исполняемый файл которые они могут вызывать из любой точки командной строки с помощью:

$ myappname arg1 arg2

важные части моего setup.py похожи:

from setuptools import setup, find_packages
setup(
  name='code2flow',
  scripts=['myappname/myappname.py'],
  package_dir={'myappname': 'myappname'},
  packages=find_packages(),
  )

состояние

работает:

$ sudo python setup.py install

и затем в новой оболочке:

$ myapp.py

Я получаю No module named

1 ответов


проблема здесь в том, что ваш макет пакета сломан.

это происходит на месте, по крайней мере, в 2.х. Почему? Вы не получаете доступ к пакету как myappname-но тот же каталог, который является каталогом этого пакета, также является каталогом скриптов верхнего уровня, поэтому вы в конечном итоге получаете любого из своих братьев и сестер через относительный импорт старого стиля.

как только вы установите вещи, конечно, вы в конечном итоге с myappname пакет, установленный на вашем сайте-пакеты, а затем копия myappname.py установлен где-то на вашем пути, поэтому относительный импорт не может работать.

правильный способ сделать это-поместить скрипты верхнего уровня вне пакета (или, в идеале, в ).

кроме того, ваш модуль и ваш скрипт не должны иметь одинаковое имя. (Есть способы заставить это работать, но ... просто не пытайтесь.)

так, например:

myappname/
|-- setup.py
|-- myscriptname.py
|-- myappname/
|   |-- __init__.py
|   |-- src/
|      |-- __init__.py
|      |-- mainclassfile.py

конечно, до сих пор все это заставляет его делать, это ломать на месте режим точно так же, как он ломается при установке. Но, по крайней мере, это облегчает отладку, верно?

в любом случае, ваш myscriptname.py затем должен использовать абсолютный импорт:

import myappname.src.mainclassfile

и свой setup.py надо найти скрипт в нужном месте:

scripts=['myscriptname.py'],

наконец, если вам нужен код из myscriptname.py должны быть доступны внутри модуля, а также в скрипте, что нужно сделать, это переписать его в двух файлах-но если это слишком сложно для какой-то причине, вы всегда можете написать скрипт-обертку.

посмотреть организация структуры файлов и каталогов и связанные разделы в руководстве Автостопом по упаковке для получения более подробной информации.

см. Также PEP 328 подробнее об абсолютном и относительном импорте (но имейте в виду, что когда речь идет о "до Python 2.5", это действительно означает "до 2.7", а "начиная с 2.6" означает "начиная с 3.0".

для нескольких примеров пакеты, включающие скрипты, которые устанавливаются таким образом через setup.py (и, как правило, easy_install и pip), см. ipython, bpython, modulegraph, py2app и конечно easy_install и pip сами.