第十八章 程序打包
第十八章 程序打包
Setuptools和較舊的Distutils都是用于發(fā)布Python包的工具包,能夠使用Python輕松地編寫安裝腳本。這些腳本可用于生成可發(fā)布的歸檔文檔,供用戶用來編譯和安裝編寫庫。
Setuptools并非只能用于創(chuàng)建基于腳本的Python安裝程序,還可用于編譯擴(kuò)展。
通過將其與擴(kuò)展py2exe和py2app結(jié)合起來使用,還可創(chuàng)建獨(dú)立的Windows和macOS可執(zhí)行程序。
Setuptools基礎(chǔ)
如果沒有安裝Setuptools,可使用pip安裝
簡(jiǎn)單的Setuptools安裝腳本(setup.py)
請(qǐng)將代碼所示的腳本存儲(chǔ)為setup.py(這適用于所有的Setuptools安裝腳本),并確保其所在目錄包含簡(jiǎn)單模塊beyond.py。
使用這個(gè)簡(jiǎn)單的腳本
python setup.py將出現(xiàn)類似于下面的輸出:
usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]or: setup.py --help [cmd1 cmd2 ...]or: setup.py --help-commandsor: setup.py cmd --helperror: no commands supplied要獲得更多的信息,可使用開關(guān)--help或--help-commands。
執(zhí)行命令build,讓Setuptools行動(dòng)起來。
python setup.py build將出現(xiàn)類似于下面的輸出:
running build running build_py creating build creating build/lib copying beyond.py -> build/libSetuptools創(chuàng)建了一個(gè)名為build的目錄,其中包含子目錄lib。同時(shí)將將beyond.py復(fù)制到了這個(gè)子目錄中。目錄build相當(dāng)于工作區(qū),Setuptools在其中組裝包(以及編譯擴(kuò)展庫等)。安裝時(shí)不需要執(zhí)行命令build,因?yàn)楫?dāng)你執(zhí)行命令install時(shí),如果需要,命令build會(huì)自動(dòng)運(yùn)行。
在上述這個(gè)示例中,命令install將把模塊beyond.py復(fù)制到PYTHONPATH指定的特定目錄中。這應(yīng)該不會(huì)帶來風(fēng)險(xiǎn),但如果你不想弄亂系統(tǒng),應(yīng)該將其刪除。
安裝install這個(gè)模塊
python setup.py install輸出應(yīng)該非常多,其末尾的內(nèi)容類似于下面這樣:
Installed /path/to/python3.5/site-packages/Beyond-1.0-py3.5.egg Processing dependencies for Beyond==1.0 Finished processing dependencies for Beyond==1.0 byte-compiling在安裝過程中,Setuptools創(chuàng)建了一個(gè).egg文件,這是一個(gè)獨(dú)立的Python包。
在這個(gè)腳本中,只使用了Setuptools指令py_modules。如果要安裝整個(gè)包,可以類似的方式(列出包名)使用指令packages。
打包
編寫讓用戶能夠安裝模塊的腳本setup.py后,就可使用它來創(chuàng)建歸檔文件了。
這里主要介紹如何創(chuàng)建.tar.gz文件
要?jiǎng)?chuàng)建源代碼歸檔文件,可使用命令sdist(表示source distribution)。
python setup.py sdist如果執(zhí)行上述命令,可能出現(xiàn)大量的輸出,其中包括一些警告。完全可以對(duì)這些警告置若罔聞,但也可在腳本setup.py中添加author_email(類似于選項(xiàng)author),并在當(dāng)前目錄中添加文本文件README.txt。
現(xiàn)在,除目錄build外,應(yīng)該還有一個(gè)名為dist的目錄。在這個(gè)目錄中,有一個(gè)名為Beyond-1.0.tar.gz的文件。
可將其分發(fā)給他人,而對(duì)方可將其解壓縮,再使用腳本setup.py進(jìn)行安裝。
不想生成.tar.gz文件,還有其他幾種分發(fā)格式可供使用。要設(shè)置分發(fā)格式,可使用命令行開關(guān)--formats(這個(gè)開關(guān)為復(fù)數(shù)形式,表明你可指定多種用逗號(hào)分隔的格式,這樣將一次性創(chuàng)建多個(gè)歸檔文件)。要獲悉可使用的格式列表,可給命令sdist指定開關(guān)--help-formats。
編譯擴(kuò)展
假設(shè)這個(gè)源代碼文件(palindrome2.c)位于當(dāng)前目錄中(第17章中程序palindrome的源代碼),則可使用下面的setup.py腳本來編譯(并安裝)它:
一個(gè)回文檢查示例(palindrome2.c)
#include <Python.h>static PyObject *is_palindrome(PyObject *self, PyObject *args) {int i, n;const char *text;int result;if (!PyArg_ParseTuple(args, "s", &text)) {return NULL;}n=strlen(text);result = 1;for (i = 0; i <= n/2; ++i) {if (text[i] != text[n-i-1]) {result = 0;break;}}return Py_BuildValue("i", result); /* "i"表示一個(gè)整數(shù):*/}static PyMethodDef PalindromeMethods[] = {/* 方法/函數(shù)列表:*/{"is_palindrome", is_palindrome, METH_VARARGS, "Detect palindromes"},{NULL, NULL, 0, NULL} };static struct PyModuleDef palindrome = {PyModuleDef_HEAD_INIT,"palindrome", /* 模塊名 */"", /* 文檔字符串 */-1, /*存儲(chǔ)在全局變量中的信號(hào)狀態(tài) */PalindromeMethods };/* 初始化模塊的函數(shù):*/ PyMODINIT_FUNC PyInit_palindrome(void) {return PyModule_Create(&palindrome); }setup.py腳本
from setuptools import setup, Extensionsetup(name='palindrome',version='1.0',ext_modules = [Extension('palindrome', ['palindrome2.c'])] )如果使用這個(gè)腳本運(yùn)行命令install,將自動(dòng)編譯擴(kuò)展模塊palindrome再安裝它。
這里沒有指定一個(gè)模塊名列表,而是將參數(shù)ext_modules設(shè)置為一個(gè)Extension實(shí)例列表。構(gòu)造函數(shù)Extension將一個(gè)名稱和一個(gè)相關(guān)文件列表作為參數(shù);
如果只想就地編譯擴(kuò)展(在大多數(shù)UNIX系統(tǒng)中,這都將在當(dāng)前目錄中生成一個(gè)名為palindrome.so的文件),可使用如下命令:
python setup.py build_ext --inplace如果安裝了SWIG(參見第17章),可讓Setuptools直接使用它!
代碼palindrome.c的源代碼,顯然比包裝后的版本簡(jiǎn)單得多。能夠讓Setuptools使用SWIG并直接將其作為Python擴(kuò)展確實(shí)非常方便。
為此,需要做的非常簡(jiǎn)單,只需將接口文件(.i文件,palindrome.i)的名稱加入到Extension實(shí)例的文件列表中即可。
palindrome.c的源代碼
#include <string.h> int is_palindrome(char *text) {int i, n=strlen(text);for (i = 0; I <= n/2; ++i) {if (text[i] != text[n-i-1]) return 0;}return 1; }接口文件(palindrome.i)
%module palindrome%{ #include <string.h> %}extern int is_palindrome(char *text);Extension實(shí)例的文件列表
from setuptools import setup, Extensionsetup(name='palindrome',version='1.0',ext_modules = [Extension('_palindrome', ['palindrome.c','palindrome.i'])])如果用剛才的命令(build_ext,可能還要加上開關(guān)–inplace)運(yùn)行這個(gè)腳本,也將生成一個(gè).so文件(或與之等價(jià)的文件),但這次無需自己編寫包裝代碼。
這個(gè)擴(kuò)展指定了名稱_palindrome,因?yàn)镾WIG將創(chuàng)建一個(gè)名為palindrom.py的包裝器,而這個(gè)包裝器將通過名稱_palindrome導(dǎo)入一個(gè)C語言庫。
使用py2exe創(chuàng)建可執(zhí)行程序
py2exe是Setuptools的一個(gè)擴(kuò)展(可通過pip來安裝它),能夠創(chuàng)建可執(zhí)行的Windows程序(.exe文件)。
py2exe包可用來創(chuàng)建帶GUI(參見第12章)的可執(zhí)行文件。
創(chuàng)建一個(gè)空目錄,再將這個(gè)文件(hello.py)放到這個(gè)目錄中,然后創(chuàng)建一個(gè)類似于下面的setup.py文件:
beyond.py
setup.py
from distutils.core import setup import py2exesetup(console=['beyond.py'])接著運(yùn)行這個(gè)腳本:
python setup.py py2exe這將創(chuàng)建一個(gè)控制臺(tái)應(yīng)用程序(beyond.exe),還將在子目錄dist中創(chuàng)建其他幾個(gè)文件。
有關(guān)py2exe的工作原理和高級(jí)用法的詳細(xì)信息,可以查閱py2exe官網(wǎng)。
小結(jié)
| Setuptools | Setuptools工具包讓你能夠編寫安裝腳本。根據(jù)約定,這種安裝腳本被命名為setup.py。使用這種腳本,可安裝模塊、包和擴(kuò)展。 |
| Setuptools的命令 | 可使用多個(gè)命令來運(yùn)行setup.py腳本,如build、build_ext、install、sdist和bdist。 |
| 編譯擴(kuò)展 | 可使用Setuptools來自動(dòng)編譯C語言擴(kuò)展,并讓Setuptools自動(dòng)確定Python安裝位置以及該使用哪個(gè)編譯器。還可讓它自動(dòng)運(yùn)行SWIG。 |
| 可執(zhí)行的二進(jìn)制文件 | Setuptools擴(kuò)展py2exe可用來從Python程序創(chuàng)建可執(zhí)行的Windows二進(jìn)制文件以及其他一些文件(可使用安裝程序方便地安裝)。無需單獨(dú)安裝Python解釋器,就可運(yùn)行這些.exe文件。在macOS中,擴(kuò)展py2app提供了與py2exe類似的功能。 |
本章介紹的新函數(shù)
| setuptools.setup(…) | 在腳本setup.py中使用關(guān)鍵字參數(shù)配置Setuptools |
總結(jié)