1. 程式人生 > >Python3基礎之構建setup.py

Python3基礎之構建setup.py

# 技術背景 在上一篇[部落格](https://www.cnblogs.com/dechinphy/p/pyinstaller.html)中,我們介紹瞭如何使用pyinstaller將python專案打包成一個可執行檔案,並且放在系統目錄下,讓系統使用者可以直接識別到我們構造的專案。而python專案中常見的`setup.py`其實也是在執行類似的構建的功能,通過setup.py檔案可以將python包按照指定的方案進行構建,構建出來的可執行檔案是一個`egg`檔案。最後將這個egg檔案轉移到python包的統一管理路徑下,這樣我們就可以在系統內任一位置的python檔案中呼叫我們構建好的這個python庫。 # python專案示例 首先我們構造一個大概的目錄結構,專案的路徑如下所示: ```bash [dechin@dechin-manjaro test_setup]$ tree . ├── requirements.txt ├── setup.py └── ts └── __init__.py 1 directory, 3 files ``` 在一個名為`test_setup`的路徑下,作為我們最上層的專案根目錄。然後在根目錄下有需求配置檔案`requirements.txt`,我們可以在這個檔案中新增我們的python庫所依賴的其他python庫,如`numpy`、`scipy`等。而`setup.py`就是我們這裡的安裝檔案,在後面的章節中會著重提到。最後是我們的專案的核心路徑`ts`,裡面包含了我們的核心程式碼。 ## 用__init__.py檔案構造的簡單專案 在一個普通的python專案中,我們可以用`目錄.模組名.函式名`的形式來構造python專案的引用方法。但是對於一些比較簡單的庫而言,比如定義一個[二叉樹的資料結構](https://github.com/joowani/binarytree)這種簡單的專案,我們可以直接在`__init__.py`檔案裡面直接定義好所有的專案函式及內容。當然,對於一些比較大型的比較規範的專案而言,也會用`__init__.py`檔案作為一個統一的函式入口,以提升模組化專案的可用性。在本測試用例中,我們也定義了一個簡單的py核心程式碼檔案如下: ```python [dechin@dechin-manjaro test_setup]$ cat ts/__init__.py # __init__.py def p2(number): return number ** 2 def p3(number): return number ** 3 ``` 這個名為`ts`的專案具有兩個函式功能:`p2`用於計算輸入引數的平方,以及`p3`用於計算輸入引數的立方。 ## 構造setup檔案 我們主要是基於setuptools來實現一個python專案的構建,以下直接展示本專案的構建方法: ```python # setup.py import os from setuptools import setup, find_packages __version__ = '1.0' # 版本號 requirements = open('requirements.txt').readlines() # 依賴檔案 setup( name = 'ts', # 在pip中顯示的專案名稱 version = __version__, author = 'Dechin', author_email = '[email protected]', url = '', description = 'ts: Test Setup', packages = find_packages(exclude=["tests"]), # 專案中需要拷貝到指定路徑的資料夾 python_requires = '>=3.5.0', install_requires = requirements # 安裝依賴 ) ``` 在這個構建方法中,我們配置了專案的版本號(版本管理)、依賴庫、專案名稱以及需要進行構建的資料夾。比如這裡我們加了一個`exclude`的選項排除了`tests`目錄(雖然本專案中並沒有這個目錄,但是一般我們都要剔除測試目錄)。當然我們也可以用指定目錄進行構建的方法,但是這裡不做過多的贅述。 ## 依賴包配置檔案 python之所以這麼火,很大程度上就得益於其強大的生態,而這些生態都是靠別人搭建好的輪子來支撐起來的。因此大部分的python專案都會依賴於第三方的python包,在安裝的時候我們可以僅用一個檔案就進行配置: ```bash [dechin@dechin-manjaro test_setup]$ cat requirements.txt numpy==1.20.1 ``` 在`requirements.txt`的配置檔案中,我們最好是能夠指定一個固定的版本號,這樣可以確保軟體的相容性。 ## 執行安裝 按照上述的方法對我們的python專案進行編寫後,就可以開始執行構建,如果需要測試編譯可以先執行`python3 setup.py build`來進行測試,在安裝成功後再執行`install`指令,當然我們也可以直接一步執行`python3 setup.py install`指令來進行安裝: ```bash [dechin@dechin-manjaro test_setup]$ python3 setup.py install running install running bdist_egg running egg_info writing ts.egg-info/PKG-INFO writing dependency_links to ts.egg-info/dependency_links.txt writing requirements to ts.egg-info/requires.txt writing top-level names to ts.egg-info/top_level.txt reading manifest file 'ts.egg-info/SOURCES.txt' writing manifest file 'ts.egg-info/SOURCES.txt' installing library code to build/bdist.linux-x86_64/egg running install_lib running build_py creating build/lib creating build/lib/ts copying ts/__init__.py -> build/lib/ts creating build/bdist.linux-x86_64/egg creating build/bdist.linux-x86_64/egg/ts copying build/lib/ts/__init__.py -> build/bdist.linux-x86_64/egg/ts byte-compiling build/bdist.linux-x86_64/egg/ts/__init__.py to __init__.cpython-38.pyc creating build/bdist.linux-x86_64/egg/EGG-INFO copying ts.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO copying ts.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO copying ts.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO copying ts.egg-info/requires.txt -> build/bdist.linux-x86_64/egg/EGG-INFO copying ts.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO zip_safe flag not set; analyzing archive contents... creating 'dist/ts-1.0-py3.8.egg' and adding 'build/bdist.linux-x86_64/egg' to it removing 'build/bdist.linux-x86_64/egg' (and everything under it) Processing ts-1.0-py3.8.egg Copying ts-1.0-py3.8.egg to /home/dechin/anaconda3/lib/python3.8/site-packages Adding ts 1.0 to easy-install.pth file Installed /home/dechin/anaconda3/lib/python3.8/site-packages/ts-1.0-py3.8.egg Processing dependencies for ts==1.0 Searching for numpy==1.20.1 Best match: numpy 1.20.1 Adding numpy 1.20.1 to easy-install.pth file Installing f2py script to /home/dechin/anaconda3/bin Installing f2py3 script to /home/dechin/anaconda3/bin Installing f2py3.8 script to /home/dechin/anaconda3/bin Using /home/dechin/anaconda3/lib/python3.8/site-packages Finished processing dependencies for ts==1.0 ``` 安裝完成後,我們可以在pip的管理包目錄下找到我們所構建的python包: ```bash [dechin@dechin-manjaro test_setup]$ python3 -m pip list Package Version ---------------------------------- ------------------- ts 1.0 ``` 同時在執行完build指令之後,本地目錄下會生成一系列的編譯構建目錄,如build和dist等: ```bash [dechin@dechin-manjaro test_setup]$ tree . ├── build │   └── bdist.linux-x86_64 ├── dist │   └── ts-1.0-py3.8.egg ├── requirements.txt ├── setup.py ├── ts │   ├── __init__.py │   └── __pycache__ │   └── __init__.cpython-38.pyc └── ts.egg-info ├── dependency_links.txt ├── PKG-INFO ├── requires.txt ├── SOURCES.txt └── top_level.txt 6 directories, 10 files ``` 而dist目錄下的egg檔案在執行完install指令之後,會被拷貝到系統指定的python包管理路徑下,我們可以在系統中搜索到這個檔案: ```bash [dechin-root test_setup]# find / -name *ts-1.0-py3.8.egg /home/dechin/anaconda3/lib/python3.8/site-packages/ts-1.0-py3.8.egg /home/dechin/projects/2021-python/setup/test_setup/dist/ts-1.0-py3.8.egg ``` 這裡我們可以看到第一個路徑就是python包管理路徑。 ## 軟體包功能測試 在安裝完成後,我們可以在任意的路徑下引用到我們構建好的`ts`專案,比如這裡我們可以用ipython來測試一下: ```python [dechin@dechin-manjaro test_setup]$ ipython Python 3.8.5 (default, Sep 4 2020, 07:30:14) Type 'copyright', 'credits' or 'license' for more information IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: from ts import p2, p3 In [2]: p2(4) Out[2]: 16 In [3]: p3(4) Out[3]: 64 ``` 測試結果表明,我們成功的從編譯構建好的ts專案中引用了平方和立方的計算函式。 ## 安裝包的刪除 跟其他的python包一樣,我們可以用pip來統一管理,也可以用pip來直接刪除我們自己安裝的ts專案: ```bash [dechin@dechin-manjaro test_setup]$ python3 -m pip uninstall ts Found existing installation: ts 1.0 Uninstalling ts-1.0: Would remove: /home/dechin/anaconda3/lib/python3.8/site-packages/ts-1.0-py3.8.egg Proceed (y/n)? y Successfully uninstalled ts-1.0 ``` # 總結概要 一個完善的python專案,不僅需要梳理好核心程式碼的軟體架構,還需要定義好依賴檔案、編譯構建檔案、API介面文件、編碼規範門禁等。這裡我們介紹瞭如何用setup.py檔案來完善一個最簡單的python專案,這也是每一個python開源專案所必須要具備的條件。 # 版權宣告 本文首發連結為:https://www.cnblogs.com/dechinphy/p/setup.html 作者ID:DechinPhy 更多原著文章請參考:https://www.cnblogs.com/dec