簡體   English   中英

如何將所有 python 代碼打包成一個 zip 文件?

[英]How can you bundle all your python code into a single zip file?

在分發應用程序時將所有的雞蛋組合成一個 zip 文件會很方便,這樣你只需要分發一個 zip 文件和一個可執行文件(一些自定義二進制文件,它簡單地啟動,加載 zip 文件的主要功能並踢 python關閉或類似)。

我在網上看到了一些關於這樣做的討論,但沒有實際操作的例子。

我知道您可以(如果它是 zip 安全的)將雞蛋轉換為 zip 文件。

我不確定的是:

你能以某種方式將所有的雞蛋合並成一個 zip 文件嗎? 如果是這樣,如何?

你將如何從特定的雞蛋加載和運行代碼?

您如何確保該雞蛋中的代碼可以訪問所有依賴項(即 zip 文件中的其他雞蛋)?

人們經常問這類問題,得到的答案是: 使用 py2exe。 是的,我明白了,這是一種解決方案。 雖然這不是我在這里問的問題......

您可以使用常規 Python 工具自動完成大部分工作。 讓我們從干凈的 virtualenv 開始。

[zart@feena ~]$ mkdir ziplib-demo
[zart@feena ~]$ cd ziplib-demo
[zart@feena ziplib-demo]$ virtualenv .
New python executable in ./bin/python
Installing setuptools.............done.
Installing pip...............done.

現在讓我們安裝一組將進入壓縮庫的軟件包。 訣竅是強制將它們安裝到特定目錄中。

(注意:不要在命令行或 pip.conf/pip.ini 中使用 --egg 選項,因為它會破壞文件布局,使其在 zip 中不可導入)

[zart@feena ziplib-demo]$ bin/pip install --install-option --install-lib=$PWD/unpacked waitress
Downloading/unpacking waitress
  Downloading waitress-0.8.5.tar.gz (112kB): 112kB downloaded
  Running setup.py egg_info for package waitress

Requirement already satisfied (use --upgrade to upgrade): setuptools in ./lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg (from waitress)
Installing collected packages: waitress
  Running setup.py install for waitress

    Installing waitress-serve script to /home/zart/ziplib-demo/bin
Successfully installed waitress
Cleaning up...

更新:pip 現在有-t <path>開關,它與--install-option --install-lib=做同樣的事情。

現在讓我們將它們全部打包成一個 zip

[zart@feena ziplib-demo]$ cd unpacked
[zart@feena unpacked]$ ls
waitress  waitress-0.8.5-py2.7.egg-info
[zart@feena unpacked]$ zip -r9 ../library.zip *
  adding: waitress/ (stored 0%)
  adding: waitress/receiver.py (deflated 71%)
  adding: waitress/server.pyc (deflated 64%)
  adding: waitress/utilities.py (deflated 62%)
  adding: waitress/trigger.pyc (deflated 63%)
  adding: waitress/trigger.py (deflated 61%)
  adding: waitress/receiver.pyc (deflated 60%)
  adding: waitress/adjustments.pyc (deflated 51%)
  adding: waitress/compat.pyc (deflated 56%)
  adding: waitress/adjustments.py (deflated 60%)
  adding: waitress/server.py (deflated 68%)
  adding: waitress/channel.py (deflated 72%)
  adding: waitress/task.pyc (deflated 57%)
  adding: waitress/tests/ (stored 0%)
  adding: waitress/tests/test_regression.py (deflated 63%)
  adding: waitress/tests/test_functional.py (deflated 88%)
  adding: waitress/tests/test_parser.pyc (deflated 76%)
  adding: waitress/tests/test_trigger.pyc (deflated 73%)
  adding: waitress/tests/test_init.py (deflated 72%)
  adding: waitress/tests/test_utilities.pyc (deflated 78%)
  adding: waitress/tests/test_buffers.pyc (deflated 79%)
  adding: waitress/tests/test_trigger.py (deflated 82%)
  adding: waitress/tests/test_buffers.py (deflated 86%)
  adding: waitress/tests/test_runner.py (deflated 75%)
  adding: waitress/tests/test_init.pyc (deflated 69%)
  adding: waitress/tests/__init__.pyc (deflated 21%)
  adding: waitress/tests/support.pyc (deflated 48%)
  adding: waitress/tests/test_utilities.py (deflated 73%)
  adding: waitress/tests/test_channel.py (deflated 87%)
  adding: waitress/tests/test_task.py (deflated 87%)
  adding: waitress/tests/test_functional.pyc (deflated 82%)
  adding: waitress/tests/__init__.py (deflated 5%)
  adding: waitress/tests/test_compat.pyc (deflated 53%)
  adding: waitress/tests/test_receiver.pyc (deflated 79%)
  adding: waitress/tests/test_adjustments.py (deflated 78%)
  adding: waitress/tests/test_adjustments.pyc (deflated 74%)
  adding: waitress/tests/test_server.pyc (deflated 73%)
  adding: waitress/tests/fixtureapps/ (stored 0%)
  adding: waitress/tests/fixtureapps/filewrapper.pyc (deflated 59%)
  adding: waitress/tests/fixtureapps/getline.py (deflated 37%)
  adding: waitress/tests/fixtureapps/nocl.py (deflated 47%)
  adding: waitress/tests/fixtureapps/sleepy.pyc (deflated 44%)
  adding: waitress/tests/fixtureapps/echo.py (deflated 40%)
  adding: waitress/tests/fixtureapps/error.py (deflated 52%)
  adding: waitress/tests/fixtureapps/nocl.pyc (deflated 48%)
  adding: waitress/tests/fixtureapps/getline.pyc (deflated 32%)
  adding: waitress/tests/fixtureapps/writecb.pyc (deflated 42%)
  adding: waitress/tests/fixtureapps/toolarge.py (deflated 37%)
  adding: waitress/tests/fixtureapps/__init__.pyc (deflated 20%)
  adding: waitress/tests/fixtureapps/writecb.py (deflated 50%)
  adding: waitress/tests/fixtureapps/badcl.pyc (deflated 44%)
  adding: waitress/tests/fixtureapps/runner.pyc (deflated 58%)
  adding: waitress/tests/fixtureapps/__init__.py (stored 0%)
  adding: waitress/tests/fixtureapps/filewrapper.py (deflated 74%)
  adding: waitress/tests/fixtureapps/runner.py (deflated 41%)
  adding: waitress/tests/fixtureapps/echo.pyc (deflated 42%)
  adding: waitress/tests/fixtureapps/groundhog1.jpg (deflated 24%)
  adding: waitress/tests/fixtureapps/error.pyc (deflated 48%)
  adding: waitress/tests/fixtureapps/sleepy.py (deflated 42%)
  adding: waitress/tests/fixtureapps/toolarge.pyc (deflated 43%)
  adding: waitress/tests/fixtureapps/badcl.py (deflated 45%)
  adding: waitress/tests/support.py (deflated 52%)
  adding: waitress/tests/test_task.pyc (deflated 78%)
  adding: waitress/tests/test_channel.pyc (deflated 78%)
  adding: waitress/tests/test_regression.pyc (deflated 68%)
  adding: waitress/tests/test_parser.py (deflated 80%)
  adding: waitress/tests/test_server.py (deflated 78%)
  adding: waitress/tests/test_receiver.py (deflated 87%)
  adding: waitress/tests/test_compat.py (deflated 51%)
  adding: waitress/tests/test_runner.pyc (deflated 72%)
  adding: waitress/__init__.pyc (deflated 50%)
  adding: waitress/channel.pyc (deflated 58%)
  adding: waitress/runner.pyc (deflated 54%)
  adding: waitress/buffers.py (deflated 74%)
  adding: waitress/__init__.py (deflated 61%)
  adding: waitress/runner.py (deflated 58%)
  adding: waitress/parser.py (deflated 69%)
  adding: waitress/compat.py (deflated 69%)
  adding: waitress/buffers.pyc (deflated 69%)
  adding: waitress/utilities.pyc (deflated 60%)
  adding: waitress/parser.pyc (deflated 53%)
  adding: waitress/task.py (deflated 72%)
  adding: waitress-0.8.5-py2.7.egg-info/ (stored 0%)
  adding: waitress-0.8.5-py2.7.egg-info/dependency_links.txt (stored 0%)
  adding: waitress-0.8.5-py2.7.egg-info/installed-files.txt (deflated 83%)
  adding: waitress-0.8.5-py2.7.egg-info/top_level.txt (stored 0%)
  adding: waitress-0.8.5-py2.7.egg-info/PKG-INFO (deflated 65%)
  adding: waitress-0.8.5-py2.7.egg-info/not-zip-safe (stored 0%)
  adding: waitress-0.8.5-py2.7.egg-info/SOURCES.txt (deflated 71%)
  adding: waitress-0.8.5-py2.7.egg-info/entry_points.txt (deflated 33%)
  adding: waitress-0.8.5-py2.7.egg-info/requires.txt (deflated 5%)
[zart@feena unpacked]$ cd ..

請注意,這些文件應該在 zip 的頂部,您不能只zip -r9 library.zip unpacked

檢查結果:

[zart@feena ziplib-demo]$ PYTHONPATH=library.zip python
Python 2.7.1 (r271:86832, Apr 12 2011, 16:15:16)
[GCC 4.6.0 20110331 (Red Hat 4.6.0-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import waitress
>>> waitress
<module 'waitress' from '/home/zart/ziplib-demo/library.zip/waitress/__init__.pyc'>
>>>
>>> from wsgiref.simple_server import demo_app
>>> waitress.serve(demo_app)
serving on http://0.0.0.0:8080
^C>>>

更新:從 python 3.5 開始,還有zipapp 模塊可以幫助將整個包捆綁到 .pyz 文件中。 對於更復雜的需求pyinstallerpy2exepy2app可能更適合該法案。

您可以使用標准庫中的zipapp模塊來創建可執行的 Python zip 存檔。 它從 Python 3.5 開始可用。

創建包的一種方法是添加一個名為__main__.py的頂級文件,該文件將是執行 zip 可執行存檔時 Python 運行的腳本。

假設你的目錄結構現在是這樣的:

└── myapp
    ├── __main__.py
    ├── myprog1.py
    └── myprog2.py

如果您的代碼具有外部依賴項(例如在名為requirements.txt的文件中列出),請使用以下命令將它們安裝到目錄中:

pip3 install -r requirements.txt --target myapp/

注意 1:這將使用外部依賴項填充myapp/目錄。

注意 2:Debian/Ubuntu 用戶可能需要為pip3使用--system選項,因為 pip 的 Debian/Ubuntu 版本似乎默認使用--user

然后,使用以下命令創建 zip 可執行存檔:

python3 -m zipapp myapp/

這將創建一個名為myapp.pyz的 zip 可執行存檔,您可以通過運行來執行它:

python3 myapp.pyz

執行 zip 可執行存檔時,運行的是__main__.py

如果除了 Python 腳本之外,還需要包含 Python 腳本使用的其他數據文件(例如文本文件、PNG 圖像等),請參閱: python:可執行的 zip 文件可以包含數據文件嗎?

如果 zip 文件在頂層包含 __main__.py[c] 文件,則 Python 會將它們作為單個腳本執行。 然后,包導入還將檢查 __main__ 正在從內部執行的 zip 內部。

所以創建你的 setup.py ( py_modules = ['__main__']在這里很重要,同時指定你的所有包和其他模塊)。

然后運行python setup.py bdist --format zip來創建 zip 文件。 現在,如果您希望它是可執行的,您可以執行以下操作。 此時,您可以像執行任何其他 python 腳本一樣執行生成的 zip 文件。

閱讀本文的 Linux/Mac 用戶的另一個步驟以提高便利性(盡管可能不是您提到 py2exe 時的場景)

echo '#!/usr/bin/env python' > my_executable_zip
cat output_of_setup_py_bdist.zip >> my_executable_zip
chmod +x my_executable_zip

這只是在前面加上一個 #! 行到 zip 文件,這樣當從 shell 運行時,您不需要指定解釋器。 此時你可以像系統上的任何其他二進制文件一樣執行它,盡管它是一個充滿 python 的 zip 文件。 我通常會創建一個 makefile 來運行 setup.py,然后進行此轉換。

是的,一個 zip-file/egg 可以提供多個模塊,因此您可以將它們組合成一個文件。 然而,我非常懷疑這是一個好主意。 您仍然需要安裝該 zip 文件,並且它可能仍會與其他已安裝的版本等發生沖突。

所以首先要問的問題是目標是什么。 為什么你只想要一個文件? 是為了便於安裝,還是為了便於分發,還是什么?

只有一個文件不會真正使安裝更容易,還有其他更好的方法。 您可以讓安裝自動下載並安裝依賴項,這很容易做到。

將它們放在一個 zip 文件中仍然意味着您需要擴展該 zip 文件並運行 setup.py,這對用戶來說不是很友好。

所以只有一個文件並不能真正解決很多問題,所以問題是你要解決哪個問題。

您可以使用自解壓 zip 文件,設置為在從包含它們的同一個 .exe 文件中解壓雞蛋后啟動 Python 解釋器。

好吧,可以在您的 {app-home-dir/packages} 中創建您自己的“包/雞蛋”(例如通過在那里處理雞蛋)並在 setup.py(setuptools)中配置額外的文件以將其全部打包為單一發行版(什么是 setup.py? )。 請注意,在啟動應用程序 main 函數之前,您需要通過將 {app-home-dir/packages} 添加到 sys.path 來通知 Python 您的外部“包/雞蛋”的確切位置。 這是創建獨立包的簡單方法……但是,這會帶來依賴項及其版本、與 Ansi C 代碼混合的 Python 模塊等方面的危險。

你能以某種方式將所有的雞蛋合並成一個 zip 文件嗎? 如果是這樣,如何?

是的你可以。 Python 將從 sys.path 中添加的 zip 存檔加載(參見PEP 273 )。 如果將所有 python 庫放在一個存檔中,則該存檔將被視為一個目錄。 這就是一些 py2exe、bbfreeze 等工具可以用來隔離庫的功能。

至於如何安裝,這實際上取決於您的雞蛋的安裝方式:pip、easy_install 等。邏輯是檢查所有依賴的雞蛋並收集它們的安裝路徑,然后將雞蛋壓縮到存檔中。

你將如何從特定的雞蛋加載和運行代碼?

您需要定義加載和運行。 如果您正在談論導入模塊和包,您不必做任何特別的事情。 這是一篇關於該主題的有趣博客文章,其中包括一些警告將Python 程序打包為可運行的 ZIP 文件

您將如何確保該雞蛋中的代碼可以訪問所有依賴項(即 zip 文件中的其他雞蛋)?

只要雞蛋不是擴展(即 zip 安全),這是內置的。 另見zipimport

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM