一个示例
先直接看个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 from distutils.core import setupsetup( name = "chardet" , packages = ["chardet" ], version = "1.0.2" , description = "Universal encoding detector" , author = "Mark Pilgrim" , author_email = "mark@diveintomark.org" , url = "http://chardet.feedparser.org/" , download_url = "http://chardet.feedparser.org/download/python3-chardet-1.0.1.tgz" , keywords = ["encoding" , "i18n" , "xml" ], classifiers = [ "Programming Language :: Python" , "Programming Language :: Python :: 3" , "Development Status :: 4 - Beta" , "Environment :: Other Environment" , "Intended Audience :: Developers" , "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)" , "Operating System :: OS Independent" , "Topic :: Software Development :: Libraries :: Python Modules" , "Topic :: Text Processing :: Linguistic" , ], long_description = """\ Universal character encoding detector ------------------------------------- Detects - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants) - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese) - EUC-JP, SHIFT_JIS, ISO-2022-JP (Japanese) - EUC-KR, ISO-2022-KR (Korean) - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic) - ISO-8859-2, windows-1250 (Hungarian) - ISO-8859-5, windows-1251 (Bulgarian) - windows-1252 (English) - ISO-8859-7, windows-1253 (Greek) - ISO-8859-8, windows-1255 (Visual and Logical Hebrew) - TIS-620 (Thai) This version requires Python 3 or later; a Python 2 version is available separately. """ )
目录结构
要开始打包 Python 软件,必须先将文件和目录安排好。例如,chardet 的目录树:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 chardet/ | +--COPYING.txt | +--setup.py | +--README.txt | +--docs/ | | | +--index.html | | | +--usage.html | | | +--images/ ... | +--chardet/ | +--__init__.py | +--big5freq.py | +--...
说明
创建根目录来保存所有的目录和文件。将其以 Python 模块的名字命名。
为了适应 Windows 用户,"自述"文件应包含 .txt 扩展名 ,而且它应该使用 Windows 风格回车符。不能仅仅因为你使用了一个优秀的文本编辑器,它从命令行运行并包括它自己的宏语言,而需要让你的用户为难。(你的用户使用记事本。虽然可悲,但却是事实。)即使你工作在 Linux 或 Mac OS X 环境下,优秀的文本编辑器毫无疑问地会有一个选项,允许将文件以 Windows 风格回车符来保存。
Distutils 安装脚本应命名为 setup.py 。
如果你的Python软件只包含一个单一的 .py 文件,你应该把它和"自述"文件以及安装脚本放到根目录下。但 chardet 并不是单一的 .py 文件,它是一个多文件模块 。但是没关系!只需在根目录下放置 chardet 目录,这样在 chardet/ 根目录下就会有一个包含 __init__.py
文件的 chardet/ 目录。这并不是一个难题,事实上,它可以简化打包过程。
编写安装脚本
每个 Distutils 安装脚本的第一行总是相同的:
1 from distutils.core import setup
该行导入 setup()
函数,这是 Distutils 的主入口点。大部分 Distutils 安装脚本仅由一个对 setup()
方法的调用组成。
setup()
方法可以有几十个参数 。为了使每个参与者都能清楚,你必须对每个参数使用命名变量 。这不只是一项约定,还是一项硬性要求。如果尝试以非命名变量调用 setup()
方法,安装脚本会崩溃。
下面的命名变量是必需的:
name,安装包的名称。
version,安装包的版本。
author,您的全名。
author_email,您的邮件地址。
url,项目主页。如果没有一个单独的项目网站,这里可以是安装包的 PyPI 的页面地址。
虽然以下内容不是必须的,但我也建议你把他们包括在你的安装脚本里:
description
,在线的项目摘要。
long_description
,以 reStructuredText format 格式编写的多行字符串。PyPI 将其转换为 html 并在安装包中显示它。
classifiers
,下一节中将讲述的特别格式化字符串。
现在让我们看看 chardet 的安装脚本。它包含所有这些要求的和建议的参数,还有一个我没有提到: packages
。
1 2 3 4 5 6 7 8 9 from distutils.core import setupsetup( name = 'chardet' , packages = ['chardet' ], version = '1.0.2' , description = 'Universal encoding detector' , author='Mark Pilgrim' , ... )
在分发过程中,这个 packages
参数凸显出一个不幸的词汇表重叠。我们一直在谈论正在构建的“安装包”(并将潜在地出现在Python包索引中)。但是,这并不是 packages 参数所指代的。它指代的是 chardet 模块是一个多文件模块这一事实 ,有时也被称为“包 ”。packages 参数告诉 Distutils 去包含 chardet/ 目录,它的 __init__.py
文件,以及所有其他构成 chardet 模块的 .py 文件。
将包分类
Python 包索引(“PyPI”)包含成千上万的 Python 库。正确的分类数据将让人们更容易找到你的包。PyPI 让你以类别的形式浏览包 。你甚至可以选择多个类别来缩小搜索范围。分类不是你可以忽略的不可见的元数据!
你可以通过传递 classifiers 参数给 Distutils 的 setup()
方法来给你的软件分类。classifers 参数是一个字符串列表。这些字符串不是任意形式的。所有的分类字符串应该来自 PyPI 上的列表 。
你应该总是至少包括以下分类:
编程语言。特别的,你应该包括"Programming Language :: Python"和"Programming Language :: Python :: 3"。如果你不包括这些,你的包将不会出现在兼容Python 3的库列表中,它链接自每个pypi.python.org单页的侧边拦。
许可证. 当我评价一个第三方库的时候,这绝对是我寻找的第一个东西。不要让我(花太多时间)寻找这个重要的信息。不要包含一个以上的许可证分类,除非你的软件明确地在多许可证下分发。(不要在多许可证下发布你的软件,除非你不得不这样做。不要强迫别人这样做。许可证已经足够让人头痛了,不要使情况变得更糟。)
操作系统. 如果你的软件只能运行于Windows(或Mac OS X或Linux),我想要尽早知道。如果你的软件不包含任何特定平台的代码并可以在任何平台运行,请使用分类 “Operating System :: OS Independent”。多操作系统 分类仅在你的软件在不同平台需要特别支持时使用。(这并不常见。)
还建议你包括以下分类:
开发状态. 你的软件品质适合beta发布么?适合Alpha发布么?还是Pre-alpha?在这里面选择一个吧。要诚实点。
目标用户. 谁会下载你的软件?最常见的选项包括: Developers、 End Users/Desktop、 Science/Research 和 System Administrators。
框架. 如果你的软件是像 Django 或 Zope 这样较大的框架的插件,请包含适当的 Framework 分类。如果不是,请忽略它。
主题. 有 大量的主题 可供选择 ,选择所有的适用项。
示例
Django 的分类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Categories Development Status :: 5 - Production/Stable Environment :: Web Environment Framework :: Django Intended Audience :: Developers License :: OSI Approved :: BSD License Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 2.6 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3.2 Programming Language :: Python :: 3.3 Topic :: Internet :: WWW/HTTP Topic :: Internet :: WWW/HTTP :: Dynamic Content Topic :: Internet :: WWW/HTTP :: WSGI Topic :: Software Development :: Libraries :: Application Frameworks Topic :: Software Development :: Libraries :: Python Modules
通过清单指定附加文件
默认情况下,Distutils 将把下列文件包含在你的发布包中:
README.txt
setup.py
由列在 packages 参数中的多模块文件所需的 .py 文件
在 py_modules 参数中列出的单独 .py 文件
但对于 chardet 项目,我们还希望包含 COPYING.txt 许可文件和含有图像与 html 文件的整个 docs/ 目录。要让 Distutils 在构建 chardet 发布包时包含这些额外的文件和目录,你需要创建一个 manifest file 。
清单文件是一个名为 MANIFEST.in 的文本文件。将它放置在项目的根目录下,同 README.txt 和 setup.py 一起。清单文件并不是 Python 脚本,它是文本文件,其中包含一系列 Distutils 定义格式的命令。清单命令允许你包含或排除特定的文件和目录。
以下是 chardet 项目的全部清单文件:
1 2 include COPYING.txt recursive-include docs *.html *.css *.png *.gif
第一行是不言自明的:包含项目根目录的 COPYING.txt 文件。
第二行有些复杂。recursive-include 命令需要一个目录名和至少一个文件名。文件名并不限于特定的文件,可以包含通配符。这行的意思是“看到在项目根目录下的 docs/ 目录了吗?在该目录下(递归地)查找 .html、 .css、 .png 和 .gif 文件。我希望将他们都包含在我的发布包中。”
检查安装脚本的错误
有许多事情需要留意。Distutils带有一个内置的验证命令,它检查是否所有必须的元数据都体现在你的安装脚本中。例如,如果你忘记包含 version 参数,Distutils 会提醒你。
1 2 3 c:\Users\pilgrim\chardet> c:\python31\python.exe setup.py check running check warning: check: missing required meta-data: version
当你包含了 version 参数(和所有其他所需的元数据)时, check 命令将如下所示:
1 2 c:\Users\pilgrim\chardet> c:\python31\python.exe setup.py check running check
创建发布源
Distutils 支持构建多种类型的发布包。至少,你应该建立一个“源代码分发”,其中包含源代码,你的Distutils 安装脚本,“Readme”文件和你想要包含其他文件 。为了建立一个源代码分发,传递 sdist 命令给你的 Distutils 安装脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 c:\Users\pilgrim\chardet> c:\python31\python.exe setup.py sdist running sdist running check reading manifest template 'MANIFEST.in' writing manifest file 'MANIFEST' creating chardet-1.0.2 creating chardet-1.0.2\chardet creating chardet-1.0.2\docs creating chardet-1.0.2\docs\images copying files to chardet-1.0.2... copying COPYING -> chardet-1.0.2 copying README.txt -> chardet-1.0.2 copying setup.py -> chardet-1.0.2 copying chardet\__init__.py -> chardet-1.0.2\chardet copying chardet\big5freq.py -> chardet-1.0.2\chardet ... copying chardet\universaldetector.py -> chardet-1.0.2\chardet copying chardet\utf8prober.py -> chardet-1.0.2\chardet copying docs\faq.html -> chardet-1.0.2\docs copying docs\history.html -> chardet-1.0.2\docs copying docs\how-it-works.html -> chardet-1.0.2\docs copying docs\index.html -> chardet-1.0.2\docs copying docs\license.html -> chardet-1.0.2\docs copying docs\supported-encodings.html -> chardet-1.0.2\docs copying docs\usage.html -> chardet-1.0.2\docs copying docs\images\caution.png -> chardet-1.0.2\docs\images copying docs\images\important.png -> chardet-1.0.2\docs\images copying docs\images\note.png -> chardet-1.0.2\docs\images copying docs\images\permalink.gif -> chardet-1.0.2\docs\images copying docs\images\tip.png -> chardet-1.0.2\docs\images copying docs\images\warning.png -> chardet-1.0.2\docs\images creating dist creating 'dist\chardet-1.0.2.zip' and adding 'chardet-1.0.2' to it adding 'chardet-1.0.2\COPYING' adding 'chardet-1.0.2\PKG-INFO' adding 'chardet-1.0.2\README.txt' adding 'chardet-1.0.2\setup.py' adding 'chardet-1.0.2\chardet\big5freq.py' adding 'chardet-1.0.2\chardet\big5prober.py' ... adding 'chardet-1.0.2\chardet\universaldetector.py' adding 'chardet-1.0.2\chardet\utf8prober.py' adding 'chardet-1.0.2\chardet\__init__.py' adding 'chardet-1.0.2\docs\faq.html' adding 'chardet-1.0.2\docs\history.html' adding 'chardet-1.0.2\docs\how-it-works.html' adding 'chardet-1.0.2\docs\index.html' adding 'chardet-1.0.2\docs\license.html' adding 'chardet-1.0.2\docs\supported-encodings.html' adding 'chardet-1.0.2\docs\usage.html' adding 'chardet-1.0.2\docs\images\caution.png' adding 'chardet-1.0.2\docs\images\important.png' adding 'chardet-1.0.2\docs\images\note.png' adding 'chardet-1.0.2\docs\images\permalink.gif' adding 'chardet-1.0.2\docs\images\tip.png' adding 'chardet-1.0.2\docs\images\warning.png' removing 'chardet-1.0.2' (and everything under it)
有几件事情需要注意:
Distutils发现了清单文件( MANIFEST.in )
Distutils 成功地解析了清单文件,并添加了我们所需要的文件—— COPYING.txt 和在 docs/ 目录下的 html 与图像文件。
如果你进入你的项目目录,你会看到 Distutils 创建了一个 dist/ 目录。你可以分发在 dist/ 目录中的 .zip 文件。
1 2 3 4 5 6 7 8 9 10 11 c:\Users\pilgrim\chardet> dir dist Volume in drive C has no label. Volume Serial Number is DED5-B4F8 Directory of c:\Users\pilgrim\chardet\dist 07/30/2009 06:29 PM <DIR> . 07/30/2009 06:29 PM <DIR> .. 07/30/2009 06:29 PM 206,440 chardet-1.0.2.zip 1 File(s) 206,440 bytes 2 Dir(s) 61,424,635,904 bytes free
创建图形化安装程序
在我看来,每一个 Python 库都应该为 Windows 用户提供图形安装程序。这很容易做(即使你并没有运行 Windows ),而且 Windows 用户会对此表示感激。
通过传递 bdist_wininst 命令到你的 Distutils 安装脚本,它可以为你创建一个图形化的 Windows 安装程序 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 c:\Users\pilgrim\chardet> c:\python31\python.exe setup.py bdist_wininst running bdist_wininst running build running build_py creating build creating build\lib creating build\lib\chardet copying chardet\big5freq.py -> build\lib\chardet copying chardet\big5prober.py -> build\lib\chardet ... copying chardet\universaldetector.py -> build\lib\chardet copying chardet\utf8prober.py -> build\lib\chardet copying chardet\__init__.py -> build\lib\chardet installing to build\bdist.win32\wininst running install_lib creating build\bdist.win32 creating build\bdist.win32\wininst creating build\bdist.win32\wininst\PURELIB creating build\bdist.win32\wininst\PURELIB\chardet copying build\lib\chardet\big5freq.py -> build\bdist.win32\wininst\PURELIB\chardet copying build\lib\chardet\big5prober.py -> build\bdist.win32\wininst\PURELIB\chardet ... copying build\lib\chardet\universaldetector.py -> build\bdist.win32\wininst\PURELIB\chardet copying build\lib\chardet\utf8prober.py -> build\bdist.win32\wininst\PURELIB\chardet copying build\lib\chardet\__init__.py -> build\bdist.win32\wininst\PURELIB\chardet running install_egg_info Writing build\bdist.win32\wininst\PURELIB\chardet-1.0 .2 -py3.1 .egg-info creating 'c:\users\pilgrim\appdata\local\temp\tmp2f4h7e.zip' and adding '.' to it adding 'PURELIB\chardet-1.0.2-py3.1.egg-info' adding 'PURELIB\chardet\big5freq.py' adding 'PURELIB\chardet\big5prober.py' ... adding 'PURELIB\chardet\universaldetector.py' adding 'PURELIB\chardet\utf8prober.py' adding 'PURELIB\chardet\__init__.py' removing 'build\bdist.win32\wininst' (and everything under it) c:\Users\pilgrim\chardet> dir dist c:\Users\pilgrim\chardet>dir dist Volume in drive C has no label. Volume Serial Number is AADE-E29F Directory of c:\Users\pilgrim\chardet\dist 07/30 /2009 10 :14 PM <DIR> . 07/30 /2009 10 :14 PM <DIR> .. 07/30 /2009 10 :14 PM 371 ,236 chardet-1.0 .2 .win32.exe 07/30 /2009 06:29 PM 206 ,440 chardet-1.0 .2 .zip 2 File(s) 577 ,676 bytes 2 Dir(s) 61 ,424 ,070,656 bytes free
Distutils 也可以帮助你为 Linux 用户构建可安装包 。但这可能不值得你浪费时间。如果你希望在 Linux 中分发你的软件,你最好将时间花在与那些社区成员进行交流上,他们专门为主流 Linux 发行版打包软件。
将软件添加到 Python 安装包列表
上传软件到 Python 包索引需要三个步骤。
要注册自己,访问 PyPI用户注册页面 。输入你想要的用户名和密码,提供一个有效的电子邮件地址,然后点击 Register 按钮。(如果你有一个 pgp 或 gpg 密钥,你也可以提供。如果你没有或者不知道这是什么意思,不用担心。)检查你的电子邮件,在几分钟之内,你应该会收到一封来自 PyPI 的包含验证链接的邮件。点击链接以完成注册过程。
现在,你需要在PyPI注册你的软件并上传它。你可以用一步完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 c:\Users\pilgrim\chardet> c:\python31\python.exe setup.py register sdist bdist_wininst upload running register We need to know who you are, so please choose either: 1. use your existing login, 2. register as a new user, 3. have the server generate a new password for you (and email it to you), or 4. quit Your selection [default 1]: 1 Username: MarkPilgrim Password: Registering chardet to http://pypi.python.org/pypi Server response (200): OK running sdist ... output trimmed for brevity ... running bdist_wininst ... output trimmed for brevity ... running upload Submitting dist\chardet-1.0.2.zip to http://pypi.python.org/pypi Server response (200): OK Submitting dist\chardet-1.0.2.win32.exe to http://pypi.python.org/pypi Server response (200): OK I can store your PyPI login so future submissions will be faster. (the login will be stored in c:\home\.pypirc) Save your login (y/N)?n
发布新版本
如果你想发布一个新版本,只需以新的版本号更新 setup.py 文件,然后再一次运行相同的上传命令:
1 c:\Users\pilgrim\chardet> c:\python31\python.exe setup.py register sdist bdist_wininst upload
Python 打包工具的一些可能的将来
Python 还存在许多其他的框架,有的重在安装,有的重在测试,还有的重在部署:
以下框架重在安装
Setuptools
Pip
Distribute
以下框架重在测试和部署
virtualenv
zc.buildout
Paver
Fabric
py2exe
深入阅读
通过 Distutils 发布 Python 模块
核心发布功能 列出了 setup() 函数的所有可能参数
Distutils食谱
Python 打包生态系统
关于打包
对 “关于打包” 的几点纠错