Как собрать один файл Python из нескольких скриптов?
У меня есть простой python script, который импортирует различные другие модули, которые я написал (и так далее). Из-за моей среды мой PYTHONPATH довольно длинный. Я также использую Python 2.4.
Что мне нужно сделать - это каким-то образом упаковать мои script и все зависимости, которые не являются частью стандартного питона, поэтому я могу отправить один файл в другую систему, где я хочу ее выполнить. Я знаю, что целевая версия python такая же, но на Linux, где я нахожусь в Windows. В противном случае я бы просто использовал py2exe.
В идеале я бы хотел отправить файл .py, который каким-то образом внедряет все необходимые модули, но я бы согласился на автоматическое создание zip, я могу просто разархивировать, причем необходимые модули все в одном каталоге.
Я посмотрел на различные упаковочные решения, но я не могу найти подходящего способа сделать это. Я что-то пропустил?
[править] Я, кажется, не совсем понятен в том, что мне нужно. Я в основном ищу что-то вроде py2exe, которое создаст один файл (или 2 файла) из заданного python script, автоматически включающий все импортированные модули.
Например, если у меня есть следующие два файла:
[\foo\module.py]
def example():
print "Hello"
[\bar\program.py]
import module
module.example()
И я запустил:
cd \bar
set PYTHONPATH=\foo
program.py
Тогда это сработает. Я хочу, чтобы я мог сказать:
magic program.py
и в конечном итоге с одним файлом или, возможно, с файлом и zip, который затем я могу скопировать в linux и запустить. Я не хочу устанавливать свои модули в целевой Linux-системе.
Ответы
Ответ 1
Я придумал решение, включающее модуль, компилятор и функцию zip, которая работает хорошо. К сожалению, я не могу вставить рабочую программу здесь, поскольку она смешивается с другим нерелевантным кодом, но вот некоторые фрагменты:
zipfile = ZipFile(os.path.join(dest_dir, zip_name), 'w', ZIP_DEFLATED)
sys.path.insert(0, '.')
finder = ModuleFinder()
finder.run_script(source_name)
for name, mod in finder.modules.iteritems():
filename = mod.__file__
if filename is None:
continue
if "python" in filename.lower():
continue
subprocess.call('"%s" -OO -m py_compile "%s"' % (python_exe, filename))
zipfile.write(filename, dest_path)
Ответ 2
Я нашел это полезным:
http://blog.ablepear.com/2012/10/bundling-python-files-into-stand-alone.html
Короче говоря, вы можете заархивировать ваши модули и включить в них файл __main__.py
, который позволит вам запускать его так:
python3 app.zip
Поскольку мое приложение маленькое, я сделал ссылку из основного сценария на __main__.py
.
Приложение:
Вы также можете сделать zip самоисполняемым в UNIX-подобных системах, добавив одну строку в верхней части файла. Это может быть важно для сценариев, использующих Python3.
echo '#!/usr/bin/env python3' | cat - app.zip > app
chmod a+x app
Который теперь можно выполнить без указания Python
./app
Ответ 3
Используйте стикер модуль
stickytape scripts/blah --add-python-path . > /tmp/blah-standalone
Ответ 4
Вы можете попробовать преобразовать скрипт в исполняемый файл.
Во-первых, используйте:
pip install pyinstaller
После типа установки (убедитесь, что вы находитесь в каталоге с интересующим вас файлом):
pyinstaller --onefile - окно файла filename.py
Это создаст исполняемую версию вашего скрипта, содержащую все необходимые модули. Затем вы можете перенести (скопировать и вставить) этот исполняемый файл на ПК или компьютер, на котором вы хотите запустить свой скрипт.
Надеюсь, это поможет.
Ответ 5
Вы должны создать файл яйца. Это архив файлов Python.
Смотрите этот вопрос для руководства: Как создать файл яйца Python
Обновление: рассмотрим диски 2019 года
Ответ 6
Вы приняли во внимание Автоматическое создание script для распространения официального решения для упаковки.
Что вы делаете, создайте setup.py для вашей программы и укажите точки входа, которые будут превращены в исполняемые файлы, которые вы сможете запустить. Таким образом, вам не нужно менять исходный макет, сохраняя при этом возможность легко распространять и запускать программу.
Вы найдете пример в реальном приложении этой системы в gunicorn setup.py
Ответ 7
Единственный способ отправить один .py - это если код из всех различных модулей был перемещен в одиночный script, и вам нужно будет переделать все, чтобы ссылаться на новые местоположения.
Лучший способ сделать это - переместить рассматриваемые модули в подкаталоги в том же каталоге, что и ваша команда. Затем вы можете убедиться, что в подкаталоге, содержащем модуль, есть __init__.py
, который импортирует файл первичного модуля. В этот момент вы можете ссылаться на вещи через него.
Например:
Каталог приложений: /test
Каталог модулей: /test/hello
/test/hello/__init__.py
Содержание:
import sayhello
/test/hello/sayhello.py
Содержание:
def print_hello():
print 'hello!'
/test/test.py
Содержание:
#!/usr/bin/python2.7
import hello
hello.sayhello.print_hello()
Если вы запустите /test/test.py
, вы увидите, что он запускает функцию print_hello из каталога модулей в существующем каталоге, никаких изменений в вашем PYTHONPATH
не требуется.
Ответ 8
Если вы хотите упаковать свой script со всеми его зависимостями в один файл (это не будет .py файл), вы должны посмотреть virtualenv. Это инструмент, который позволяет вам создавать среду песочницы для установки пакетов Python и управлять всеми проблемами PATH, PYTHONPATH и LD_LIBRARY_PATH, чтобы убедиться, что песочница полностью автономна.
Если вы начинаете с девственного Python без каких-либо дополнительных библиотек, то easy_install
ваши зависимости в виртуальной среде, вы получите встроенный проект в virtualenv, для которого требуется только запуск Python.
Песочница - это дерево каталогов, а не один файл, но для распространения вы можете использовать tar/zip. Я никогда не пробовал распространять env, поэтому могут быть зависимости от пути, я не уверен.
Вместо этого вам может понадобиться распространить сборку script, которая создает виртуальную среду на целевой машине. zc.buildout - это инструмент, который помогает автоматизировать этот процесс, вроде как "make install", который тесно интегрирован с системой пакетов Python и PyPI,