Python打包分發工具setuptools


作為Python標准的打包及分發工具,setuptools可以說相當地簡單易用。它會隨着Python一起安裝在你的機器上。你只需寫一個簡短的setup.py安裝文件,就可以將你的Python應用打包

首先,如果你需要另外安裝setuptools,你可以使用下面的命令:

 wget http://peak.telecommunity.com/dist/ez_setup.py

sudo python ez_setup.py

第一個安裝文件

接下來讓我們編寫安裝文件,假設我們的項目名為setup-demo,包名為myapp,目錄結構如下:

setup-demo/
  ├ setup.py         # 安裝文件
  └ myapp/           # 源代碼__init__.py    
      ...

一個最基本的setup.py文件如下:

#coding:utf8
from setuptools import setup
 
setup(
    name='MyApp',         # 應用名
    version='1.0',        # 版本號
    packages=['myapp']    # 包括在安裝包內的Python包
)

執行安裝文件

有了上面的setup.py文件,我們就可以打各種包,也可以將應用安裝在本地Python環境中。

創建egg包

python setup.py bdist_egg

該命令會在當前目錄下的”dist”目錄內創建一個egg文件,名為”MyApp-1.0-py2.7.egg”。文件名格式就是”應用名-版本號-Python版本.egg”,我本地Python版本是2.7。同時你會注意到,當前目錄多了”build”和”MyApp.egg-info”子目

同上例類似,只不過創建的文件類型是tar.gz,文件名為”MyApp-1.0.tar.gz”。

安裝應用

python setup.py install

該命令會將當前的Python應用安裝到當前Python環境的”site-packages”目錄下,這樣其他程序就可以像導入標准庫一樣導入該應用的代碼了

開發方式安裝

python setup.py develop

如果應用在開發過程中會頻繁變更,每次安裝還需要先將原來的版本卸掉,很麻煩。使用”develop”開發方式安裝的話,應用代碼不會真的被拷貝到本地Python環境的”site-packages”目錄下,而是在”site-packages”目錄里創建一個指向當前應用位置的鏈接。這樣如果當前位置的源碼被改動,就會馬上反映到”site-packages”里。

引入非Python文件

上例中,我們只會將”myapp”包下的源碼打包,如果我們還想將其他非Python文件也打包,比如靜態文件(JS,CSS,圖片),應該怎么做呢?這時我們要在項目目錄下添加一個”MANIFEST.in”文件夾。假設我們把所有靜態文件都放在”static”子目錄下,現在的項目結構如下:

setup-demo/
  ├ setup.py         # 安裝文件
  ├ MANIFEST.in      # 清單文件
  └ myapp/           # 源代碼
      ├ static/      # 靜態文件目錄    __init__.py    
      ...

我們在清單文件”MANIFEST.in”中,列出想要在包內引入的目錄路徑:

recursive-include myapp/static *
recursive-include myapp/xxx *

“recursive-include”表明包含子目錄。還有一件事要做,就是在”setup.py”中將” include_package_data”參數設為True:

#coding:utf8
from setuptools import setup
 
setup(
    name='MyApp',         # 應用名
    version='1.0',        # 版本號
    packages=['myapp'],   # 包括在安裝包內的Python包
    include_package_data=True    # 啟用清單文件MANIFEST.in
)

之后再次打包或者安裝,”myapp/static”目錄下的所有文件都會被包含在內。如果你想排除一部分文件,可以在setup.py中使用”exclude_package_date”參數,比如:

setup(
    ...
    include_package_data=True,    # 啟用清單文件MANIFEST.in
    exclude_package_date={'':['.gitignore']}
)

上面的代碼會將所有”.gitignore”文件排除在包外。如果上述”exclude_package_date”對象屬性不為空,比如”{‘myapp’:[‘.gitignore’]}”,就表明只排除”myapp”包下的所有”.gitignore”文件。

自動安裝依賴

我們的應用會依賴於第三方的Python包,雖然可以在說明文件中要求用戶提前安裝依賴包,但畢竟很麻煩,用戶還有可能裝錯版本。其實我們可以在setup.py文件中指定依賴包,然后在使用setuptools安裝應用時,依賴包的相應版本就會被自動安裝。讓我們來修改上例中的setup.py文件,加入”install_requires”參數:

#coding:utf8
from setuptools import setup
 
setup(
    name='MyApp',         # 應用名
    version='1.0',        # 版本號
    packages=['myapp'],   # 包括在安裝包內的Python包
    include_package_data=True,    # 啟用清單文件MANIFEST.in
    exclude_package_date={'':['.gitignore']},
    install_requires=[    # 依賴列表
        'Flask>=0.10',
        'Flask-SQLAlchemy>=1.5,<=2.1'
    ]
)

上面的代碼中,我們聲明了應用依賴Flask 0.10及以上版本,和Flask-SQLAlchemy 1.5及以上、2.1及以下版本。setuptools會先檢查本地有沒有符合要求的依賴包,如果沒有的話,就會從PyPI中獲得一個符合條件的最新的包安裝到本地。

執行下試試,會發現不但Flask 0.10.1(當前最新版本)被自動安裝了,連Flask的依賴包Jinja2和Werkzeug也被自動安裝了

如果應用依賴的包無法從PyPI中獲取怎么辦,我們需要指定其下載路徑:

setup(
    ...
    install_requires=[    # 依賴列表
        'Flask>=0.10',
        'Flask-SQLAlchemy>=1.5,<=2.1'
    ],
    dependency_links=[    # 依賴包下載路徑
        'http://example.com/dependency.tar.gz'
    ]
)

路徑應指向一個egg包或tar.gz包,也可以是個包含下載地址(一個egg包或tar.gz包)的頁面。個人建議直接指向文件。

自動搜索Python包

之前我們在setup.py中指定了”packages=[‘myapp’]”,說明將Python包”myapp”下的源碼打包。如果我們的應用很大,Python包很多怎么辦。大家看到這個參數是一個列表,我們當然可以將所有的源碼包都列在里面,但肯定很多人覺得這樣做很傻。的確,setuptools提供了”find_packages()”方法來自動搜索可以引入的Python包:

#coding:utf8
from setuptools import setup, find_packages
 
setup(
    name='MyApp',               # 應用名
    version='1.0',              # 版本號
    packages=find_packages(),   # 包括在安裝包內的Python包
    include_package_data=True,   # 啟用清單文件MANIFEST.in
    exclude_package_date={'':['.gitignore']},
    install_requires=[          # 依賴列表
        'Flask>=0.10',
        'Flask-SQLAlchemy>=1.5,<=2.1'
    ]
)

這樣當前項目內所有的Python包都會自動被搜索到並引入到打好的包內。”find_packages()”方法可以限定你要搜索的路徑,比如使用”find_packages(‘src’)”就表明只在”src”子目錄下搜索所有的Python包。

補充

  • zip_safe參數

  決定應用是否作為一個zip壓縮后的egg文件安裝在當前Python環境中,還是作為一個以.egg結尾的目錄安裝在當前環境中。因為有些工具不支持zip壓縮文件,而且壓縮后的包也不方便調試,所以建議將其設為False:”zip_safe=False”。

  • 描述信息

部分參數提供了更多當前應用的細節信息,對打包安裝並無任何影響,比如:

setup(
    ...
    author = "Billy He",
    author_email = "billy@bjhee.com",
    description = "This is a sample package",
    license = "MIT",
    keywords = "hello world example",
    url = "http://example.com/HelloWorld/",   # 項目主頁
    long_description=__doc__,   # 從代碼中獲取文檔注釋
)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM