打包Python项目
本教程将指导您如何打包一个简单的Python项目。它将向您展示如何添加必要的文件和结构来创建包,如何构建包以及如何将其上载到Python包索引。
一个简单的项目
本教程使用一个名为的简单项目example_pkg
。如果您不熟悉Python的模块和导入包,请花几分钟时间阅读包含文件包和模块的Python文档。
要在本地创建此项目,请创建以下文件结构:
1 | /example_pkg |
创建此结构后,您将需要在顶级文件夹中运行本教程中的所有命令 - 所以一定要确保。cd example_pkg
您还应该编辑example_pkg/__init__.py
并在其中放入以下代码:
1 | name = "example_pkg" |
这只是为了您可以在本教程后面验证它是否正确安装。
创建包文件
现在,您将创建一些文件来打包此项目并准备分发。创建下面列出的新文件 - 您将在以下步骤中向其添加内容。
1 | /example_pkg |
创建的setup.py
setup.py
是setuptools的构建脚本。它告诉setuptools你的包(例如名称和版本)以及要包含的代码文件。
打开setup.py
并输入以下内容,您可以根据需要个性化值:
1 | import setuptools |
setup()
有几个论点。此示例包使用相对最小的集:
name
是您的包的名称。只要包含字母,数字_
和,就可以是任何名称-
。它也不能在pypi.org上使用。version
是包版本看 PEP 440有关版本的更多详细信息。author
并author_email
用于识别包的作者。description
是一个简短的,一句话的包的总结。long_description
是包的详细说明。这显示在Python Package Index的包详细信息包中。在这种情况下,加载长描述README.md
是一种常见模式。long_description_content_type
告诉索引什么类型的标记用于长描述。在这种情况下,它是Markdown。url
是项目主页的URL。对于许多项目,这只是一个指向GitHub,GitLab,Bitbucket或类似代码托管服务的链接。packages
是应包含在分发包中的所有Python 导入包的列表。我们可以使用 自动发现所有包和子包,而不是手动列出每个包。在这种情况下,包列表将是example_pkg,因为它是唯一存在的包。find_packages()
classifiers
告诉索引并点一些关于你的包的其他元数据。在这种情况下,该软件包仅与Python 3兼容,根据MIT许可证进行许可,并且与操作系统无关。您应始终至少包含您的软件包所使用的Python版本,软件包可用的许可证以及您的软件包将使用的操作系统。有关分类器的完整列表,请参阅https://pypi.org/classifiers/。
除了这里提到的还有很多。有关详细信息,请参阅 打包和分发项目。
创建README.md
打开README.md
并输入以下内容。如果您愿意,可以自定义此项。
1 | # Example Package |
创建许可证
上传到Python Package Index的每个包都包含许可证,这一点很重要。这告诉用户安装您的软件包可以使用您的软件包的条款。有关选择许可证的帮助,请参阅 https://choosealicense.com/。选择许可证后,打开 LICENSE
并输入许可证文本。例如,如果您选择了MIT许可证:
1 | Copyright (c) 2018 The Python Packaging Authority |
生成分发档案
下一步是为包生成分发包。这些是上传到包索引的档案,可以通过pip安装。
确保您拥有setuptools
并wheel
安装了最新版本:
1 | python3 -m pip install --user --upgrade setuptools wheel |
小费
如果您在安装这些软件时遇到问题,请参阅 安装软件包教程
现在从setup.py
位于的同一目录运行此命令:
1 | python3 setup.py sdist bdist_wheel |
此命令应输出大量文本,一旦完成,应在dist
目录中生成两个文件:
1 | dist/ |
注意
如果您遇到麻烦,请复制输出并提出有关包装问题的问题,我们会尽力为您提供帮助!
该tar.gz
文件是源存档,而该.whl
文件是 构建的分发。较新的pip版本优先安装构建的发行版,但如果需要,将回退到源代码存档。您应该始终上传源存档并为项目兼容的平台提供构建的存档。在这种情况下,我们的示例包在任何平台上都与Python兼容,因此只需要一个构建的发行版。
上传分发档案
最后,是时候将您的包上传到Python Package Index了!
您需要做的第一件事是在Test PyPI上注册一个帐户。Test PyPI是用于测试和实验的包索引的单独实例。这对于像我们不一定想要上传到真实索引的本教程那样很棒。要注册帐户,请访问https://test.pypi.org/account/register/并完成该页面上的步骤。在您上传任何软件包之前,您还需要验证您的电子邮件地址。有关Test PyPI的更多详细信息,请参阅 使用TestPyPI。
现在您已注册,您可以使用twine上传分发包。你需要安装Twine:
1 | python3 -m pip install --user --upgrade twine |
安装完成后,运行Twine上传所有存档dist
:
1 | twine upload --repository-url https://test.pypi.org/legacy/ dist/* |
系统将提示您输入使用Test PyPI注册的用户名和密码。命令完成后,您应该看到与此类似的输出:
1 | Uploading distributions to https://test.pypi.org/legacy/ |
注意
如果您收到错误消息,则需要为您的包选择一个唯一的名称。一个不错的选择 。更新参数 ,删除文件夹,然后 重新生成存档。The user '[your username]' isn't allowed to upload to project'example-pkg'`
example_pkg_your_usernamename
setup.pydist`
上传后,您的包应该可以在TestPyPI上查看,例如,https: //test.pypi.org/project/example-pkg
安装新上传的软件包
您可以使用pip来安装包并验证它是否有效。创建一个新的virtualenv(请参阅安装包以获取详细说明)并从TestPyPI安装包:
1 | python3 -m pip install --index-url https://test.pypi.org/simple/ example_pkg |
注意
如果在预览步骤中使用了不同的包名称,请example_pkg
在上面的命令中使用您的包名称替换 。
pip应该从Test PyPI安装包,输出应该如下所示:
1 | Collecting example_pkg |
您可以通过导入模块并引用先前name
放置的属性来测试它是否已正确安装__init__.py
。
运行Python解释器(确保你仍然在你的virtualenv中):
1 | python |
然后导入模块并打印出name
属性。无论您给出的分发包名称是什么,这都应该是相同的 ,setup.py
因为您的导入包是example_pkg
。
>>>
1 | >>> import example_pkg |
后续步骤
恭喜,您已经打包并分发了一个Python项目! ✨🍰✨
请记住,本教程向您展示了如何将软件包上传到Test PyPI,而测试PyPI是短暂的。偶尔删除包和帐户并不罕见。如果您想将软件包上传到真正的Python软件包索引,可以通过在https://pypi.org上注册帐户并按照相同的说明进行上传,但是,使用上传软件包并输入您的帐户凭据在真正的PyPI上注册。您可以使用真正的PyPI安装包 。twine upload dist/*`
pip install your-package`
在这一点上,如果你想阅读更多关于包装的Python库,你可以做一些事情:
- 阅读有关使用setuptools在打包和分发项目中打包库的 更多信息。
- 阅读包装二进制扩展。
- 考虑诸如flit,hatch和poetry之类的setuptools的替代方案。
目录
上一主题
下一个主题
一些常见的包管理工具
- distutils
- setuptools
- distribute
- disutils2
- distlib
- pip
==创建纯 Python 或者平台 Wheels 的命令是:python setup.py bdist_wheel
==
代码打包
打包你的代码,将它共享出去,让其他的开发者使用。例如,将其打包成一个库分享给其他开发者,以便他们用在自己的应用中,或者共享给开发工具,比如 ‘py.test’。
这种代码发布方式具备的优势是其成熟的工具生态系统,例如 PyPI 和 pip,这些工具使得其他的开发者很容易下载和安装你的包,无论是用于偶然的实验,还是将其集成到大型专业的系统中。
Python 代码以这种方式发布共享是一个成熟的惯例。如果你的代码不是在 PyPI 上打包的,那么别的开发者很难找到它,也很难将它集成到他们现有的程序中。他们会严重质疑这些没有在 PyPI 上打包项目的槽糕管理,甚至认为这些项目已停止维护。
类似于这种发布代码的方式的缺点是,它依赖于开发者了解如何安装它所依赖的 Python 版本,并且能够和愿意使用类似 pip 这样的工具安装你的包所需要的其他依赖。这种做法适合发布代码给其他开发人员,但是不适合发布应用程序给终端用户使用。
Python 打包指南 提供了创建和维护 Pythond 包的一个延伸的指导。
打包的替代方案
为了发布应用程序给终端用户使用,你应该 冻结你的应用程序。
在 Linux 平台,你可以考虑 创建一个Linux发行版软件包 (例如 Debian or Ubuntu 系统中是一个.deb 文件)
对于 Python 开发者
如果你正在写一个开源的 Python 模块,PyPI 是一个适合它发布的地方,PyPI 的另一个名字 The Cheeseshop 更被人熟知。
Pip vs. easy_install
私人 PyPI
如果你想要使用源码安装一个 Python 包,而不是使用 PyPI,(即, 你的包不对外公开),你可以通过托管一个简单的 HTTP 服务器来完成,从那些包的安装路径下运行。
从一个例子入手是最好的
比如你想安装一个包,它的名字是 MyPackage.tar.gz
,假设你的目录结构使这样:
- archive
- MyPackage
- MyPackage.tar.gz
- MyPackage
代码冻结
『冻结』你的代码是指创建单个可执行文件,文件里包含所有程序代码以及 Python 解释器。
像 Dropbox、星战前夜、文明 4 和 BitTorrent 客户端都是如此。
进行这种分发的好处是你的用户不需要安装所要求的 Python 版本(或其他)即可直接运行你的应用程序。 在 Windows 上,甚至许多 Linux发行版和 OS X,系统自带的 Python 版本总是不尽如人意,此时这种分发方式就会体现其价值。
此外,终端用户软件应始终是可执行的格式。 以 .py
结尾的文件一般适用于软件工程师和系统管理员。
冻结的一个缺点是它会增加大约 2-12 MB 的发行大小。另外,如果修补了 Python 的安全漏洞, 你将需要独立负责更新分发的应用程序。
冻结的替代方案
打包你的代码 是指把你的库或工具分发给其他开发者。
Linux 下一个冻结的替代品是 Linux 分发包 (比如,对于 Debian 或 Ubuntu 是 .deb文件,而对于 Red Hat 与 SuSE 是 .rpm 文件)
冻结工具的比较
解决方案还有平台/特性支持性:
Solution | Windows | Linux | OS X | Python 3 | License | One-file mode | Zipfile import | Eggs | pkg_resources support |
---|---|---|---|---|---|---|---|---|---|
bbFreeze | yes | yes | yes | no | MIT | no | yes | yes | yes |
py2exe | yes | no | no | yes | MIT | yes | yes | no | no |
pyInstaller | yes | yes | yes | yes | GPL | yes | no | yes | no |
cx_Freeze | yes | yes | yes | yes | PSF | no | yes | yes | no |
py2app | no | no | yes | yes | MIT | no | yes | yes | yes |
注意
在 Linux 下冻结 Windows 安装包,之前只有 PyInstaller 支持,不过后来也是 停止支持了。
注意
所有解决方案都需要在 Windows 目标机器上安装了MS Visual C++ dll,除了 py2app 以外。只有 Pyinstaller 支持创建独立运行的绑定了dll 的 exe 文件,你需要在创建时传递参数
--onefile
到Configure.py
。
Windows 下的解决方案
bbFreeze
前置要求是安装 Python, Setuptools 以及 pywin32 的依赖项。
- 使用以下命令安装
bbfreeze
:
1 | $ pip install bbfreeze |
- 编写最简单的示例
bb_setup.py
:
1 | from bbfreeze import Freezer |
注意
这将适用于最基本的文件脚本。 有时候你需要高级的用法,如包含或者排除某些路径,如下:
freezer = Freezer(distdir='dist', includes=['my_code'], excludes=['docs'])
- (可选) 包含图标
1 | freezer.setIcon('my_awesome_icon.ico') |
- 为冻结器(freezer)提供 Microsoft Visual C 运行时 DLL,我们有一般有两种方法,第一种是将Microsoft Visual Studio 路径 附加您的
sys.path
中,第二种是在脚本所在同一文件夹中放置msvcp90.dll
文件。 - 开始冻结!
1 | $ python bb_setup.py |
py2exe
前置要求是安装了 Python on Windows。
- 下载并且安装 http://sourceforge.net/projects/py2exe/files/py2exe/
- 编写
setup.py
(配置选项清单):
1 | from distutils.core import setup |
1 | $ python setup.py py2exe |
- 两种方式来提供 Microsoft Visual C 运行时 DLL。两个选项: 在目标机器全局安装 dll 或者 与 .exe 一起分发 dll。
PyInstaller
前置条件是安装 Python, Setuptools 以及pywin32 依赖项.
OS X
py2app
PyInstaller
PyInstaller可用于在 Mac OS X 10.6(Snow Leopard)或更新版本上构建 Unix 可执行文件和窗口应用程序。
要安装 PyInstaller,使用 pip:
1 | $ pip install pyinstaller |
要创建标准的 Unix 可执行文件,使用 script.py
:
1 | $ pyinstaller script.py |
这会创建:
script.spec
文件, 类似于make
文件build
文件夹, 存放日志文件dist
文件夹, 存放主要的可执行文件script
,和一些依赖的Python库
script.py
会把全部内容放在同一个文件夹中。PyInstaller 将所有 script.py
用到的 Python 库放到 dist
文件夹中。所以在分发可执行文件时,会分发整个 dist
文件夹。
script.spec
文件可以编辑成 自定义构建 , 比如可以:
- 将数据文件与可执行文件绑定在一起
- 包含 PyInstaller 无法自动推断的运行时库(
.dll
或.so
文件) - 将 Python 运行时选项添加到可执行文件中
现在:代码 script.spec
可以用 pyinstaller
(而不是再次使用 script.py
)运行。
1 | $ pyinstaller script.spec |
要创建独立的 OS X 窗口应用程序,请使用 --windowed
选项:
1 | $ pyinstaller --windowed script.spec |
这将在 dist
文件夹中创建一个 script.app
。请确保在 Python 代码中 使用 GUI 软件包,例如 PyQt 或 PySide来控制应用程序的图形部分。
script.spec
有几个与 Mac OS X 应用程序捆绑有关的 选项 。 例如,要指定应用程序的图标,请使用 icon=\path\to\icon.icns
选项。