Python3基礎之構建setup.py
阿新 • • 發佈:2021-03-30
# 技術背景
在上一篇[部落格](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