本教程将指导您如何打包一个简单的Python项目。它将从0开始向您展示如何添加必要的文件和结构来创建包,如何构建包以及如何将其上传到PyPI供他人使用。
子曰:知之为不知,不知为不知,太菜也!
文章目录
项目框架 添加文件 上传并发布包文件到PyPI 让别人使用你的包 可能遇到的问题 参考文档 添加前须知 创建的setup.py 创建README.md 创建许可证 生成分发资源 创建 PyPI账号 创建用户验证文件` ~/.pypirc` 上传并完成发布 查看结果 @[toc]要点说明:
本文从最基础的创建文件开始,如果不需,请跳至上传并发布包文件到PyPI 为了防止包冲突,可采用conda的虚拟环境来搭建环境 更多细节参看官网(会有坑)项目框架
本教程使用一个名为的 example_pkg 简单项目。即使您已经有一个要打包的项目,我们仍然建议您按照本示例包使用此示例包,然后尝试使用自己的包。
TIPS: MANIFEST.in 文件用来表示忽略的文件目录,此处知道便可。
要在本地创建此项目,请创建以下文件结构:
packaging_tutorial/ ??example_pkg/ ????__init__.py
创建此结构后,您将需要在顶级文件夹中运行本教程中的所有命令 - 所以需要 cd packaging_tutorial
您还应该编辑 example_pkg/__init__.py 并在其中放入以下代码:
name?=?"example_pkg"
这只是为了让您可以在本教程后面验证它是否正确安装,并且PyPI不会使用它。
添加文件
添加前须知 假设你的包已经开发完成,并且根目录必须要有一个setup.py。 最好有一个 README.md用来描述你的包,虽然这不是必须的,但文档性说明,你最好还是要有的。 如果你需要打包代码文件夹以外的文件,比如版权信息等等,你还需要写一个 LICENSE。您现在将创建一些文件。创建下面列出的新文件,下面会详细介绍每个文件的内容。
packaging_tutorial/ ??example_pkg/ ????__init__.py ??setup.py ??LICENSE ??README.md创建的setup.py
setup.py 是setuptools的构建脚本。它告诉setuptools你的包(例如名称和版本)以及要包含的代码文件。
打开 setup.py 并输入以下内容。更新软件包名称以包含您的用户名(例如 example-pkg-theacodes ),这可确保您拥有唯一的软件包名称,并且保证和其他人的软件包不会发生冲突。
import?setuptoolswith?open("README.md",?"r")?as?fh: ????long_description?=?fh.read()setuptools.setup( ????name="example-pkg-your-username", ????version="0.0.1", ????author="Example?Author", ????author_email="author@example测试数据", ????description="A?small?example?package", ????long_description=long_description, ????long_description_content_type="text/markdown", ????url="https://github测试数据/pypa/sampleproject", ????packages=setuptools.find_packages(), ????classifiers=[ ????????"Programming?Language?::?Python?::?3", ????????"License?::?OSI?Approved?::?MIT?License", ????????"Operating?System?::?OS?Independent", ????], ????python_requires='>=3.6',)
setup() 需要注意几个点。此示例包列出了最重要的几个:
name 是包的分发名称。只能包含字母、数字和中划线。但是要保证在 pypi.org上没有重名。 请务必使用您自己的包名称更新此内容 ,因为这样尽可能的能避免和其他包名冲突。
version 是包版本。看 PEP 440有关版本的更多详细信息。
author 和author_email 用于识别包的作者。
description 是一个简短的,一句话的包的总结。
long_description是包的详细说明。这显示在PytPI的包详细信息包中。在一般情况下,README.md作为描述信息是一种常见模式。
long_description_content_type告诉索引什么类型的标记用于长描述。上面代码中,这个值为Markdown。
url是项目主页的URL。对于许多项目,可以指向GitHub,GitLab,Bitbucket或类似代码托管服务的链接。
packages是应包含在分发包中的所有Python 导入包的列表。我们可以使用find_packages()自动发现所有包和子包,而不是手动列出每个包。在这种情况下,包列表将是 example_pkg ,因为它是唯一存在的包。
classifiers给出了你的包一些额外的元数据。在上面代码中,该软件包仅与Python 3兼容,根据 MIT 许可证进行许可,并且与操作系统无关。您应始终至少包含您的软件包所使用的Python版本,软件包可用的许可证以及您的软件包将使用的操作系统。有关分类器的完整列表,请参阅这里。
除了这里提到的还有很多。有关详细信息,请参阅 打包和分发项目。
创建README.md打开README.md并输入以下内容。如果您愿意,可以自定义此项。
#?Example?Package This?is?a?simple?example?package.?You?can?use [Github-flavored?Markdown](https://guides.github测试数据/features/mastering-markdown/) to?write?your?content.创建许可证
上传到PyPI的每个包都包含许可证,这一点很重要。这告诉用户安装您的软件包需要使用您的软件包的条款。有关选择许可证的帮助,请访问。选择许可证后,打开 LICENSE 并输入许可证文本。例如,如果您选择了MIT许可证:
Copyright?(c)?2018?The?Python?Packaging?Authority Permission?is?hereby?granted,?free?of?charge,?to?any?person?obtaining?a?copy of?this?software?and?associated?documentation?files?(the?"Software"),?to?deal in?the?Software?without?restriction,?including?without?limitation?the?rights to?use,?copy,?modify,?merge,?publish,?distribute,?sublicense,?and/or?sell copies?of?the?Software,?and?to?permit?persons?to?whom?the?Software?is furnished?to?do?so,?subject?to?the?following?conditions: The?above?copyright?notice?and?this?permission?notice?shall?be?included?in?all copies?or?substantial?portions?of?the?Software. THE?SOFTWARE?IS?PROVIDED?"AS?IS",?WITHOUT?WARRANTY?OF?ANY?KIND,?EXPRESS?OR IMPLIED,?INCLUDING?BUT?NOT?LIMITED?TO?THE?WARRANTIES?OF?MERCHANTABILITY, FITNESS?FOR?A?PARTICULAR?PURPOSE?AND?NONINFRINGEMENT.?IN?NO?EVENT?SHALL?THE AUTHORS?OR?COPYRIGHT?HOLDERS?BE?LIABLE?FOR?ANY?CLAIM,?DAMAGES?OR?OTHER LIABILITY,?WHETHER?IN?AN?ACTION?OF?CONTRACT,?TORT?OR?OTHERWISE,?ARISING?FROM, OUT?OF?OR?IN?CONNECTION?WITH?THE?SOFTWARE?OR?THE?USE?OR?OTHER?DEALINGS?IN?THE SOFTWARE.生成分发资源
下一步是为包生成分发包。这些是上传到包索引的资源,可以通过pip安装。
确保您拥有setuptools和wheel并升级到了最新版本:
python3?-m?pip?install?--user?--upgrade?setuptools?wheel
提示: 如果您在安装它们时遇到问题,请参阅 安装包 教程。 现在从setup.py位于的同一目录运行此命令:
python3?setup.py?sdist?bdist_wheel
此命令应输出大量文本,一旦完成,应在 dist 目录中生成两个文件:
dist/ ??example_pkg_your_username-0.0.1-py3-none-any.whl ??example_pkg_your_username-0.0.1.tar.gz
该tar.gz文件是源存档,而该 .whl 文件是构建的发行版。较新的 pip 版本优先安装构建的发行版,但如果需要,将回退到源代码存档。您应该始终上传源存档并为项目兼容的平台提供构建的存档。
上传并发布包文件到PyPI
创建 PyPI账号非常简单,直接通过官网注册, 但是需要验证邮件并确认激活。
创建用户验证文件 ~/.pypirc提示: 如何在win中配置pypi 在自己的用户目录下新建一个空白文件命名为 .pypirc ,内容如下:
[distutils] index-servers=pypi [pypi] repository?=?https://upload.pypi.org/legacy/ username?=password?=
用户名和密码就是上一步骤所创建的,直接明文输入。如果你觉得明文密码不安全也可以留空,在后面的上传过程中会提示你手动输入。
上传并完成发布python3?-m?twine?upload?dist/*查看结果
至此,你已经成功上传了你发行包!可以在官网查看。如果正常,应该出现如下画面。
让别人使用你的包
包发布完成后,其他人只需要使用 pip 就可以安装你的包文件(将 FreeBird 换成你的包名即可)。比如:
pip?install?FreeBird
如果你更新了包,别人可以可以通过–update参数来更新:
pip?install?FreeBird?--update
您可以通过导入模块并引用先前name放置的属性来测试它是否已正确安装 __init__.py 。 运行 Python 解释器:
python
然后导入模块并打印出name属性。这应该是与你导入的包一样,而不是你给你的分发包中 setup.py 设置的名字。(上述代码中的FreeBird),因为你的导入包是 example_pkg 。
>>>?import?example_pkg >>>?example_pkg.name 'example_pkg'
可能遇到的问题
Upload failed (403) : Invalid or non-existent authentication information. 错误的用户验证信息,你需要创建一个用户验证文件 ~/.pypirc。请参阅上文。
Upload failed (403) : You are not allowed to edit ‘xxx’ package information 你需要先注册你的包才可以开始上传,运行注册命令:python setup.py register
Server response (401) : Incomplete registration; check your email 你的PyPI账户还没完成邮箱验证,你需要去注册邮箱找到一封验证邮件完成验证后再重试失败的步骤。
Server response (400) : Invalid classifier “Topic :: Software Development :: Utilities” 你的setup.py文件中的classifier信息有误,请按官网的正确分类书写classifier.
error: No dist file created in earlier command 你还没打包就开始了上传命令,建议打包和上传的操作放在一起做,比如:
python?setup?sdist?upload error:?Upload?failed?(499):?Client?Disconnected
这应该是网络问题,多重试几次。
Upload failed (400) : File already exists 文件已经存在了,你每一次上次都应该更新版本号。
参考文档
https://segmentfault测试数据/a/1190000008663126
关于作者:Java\Python技术爱好者,目前还是一枚学生小鲜肉,转载请注明原文出处。 欢迎到我的 公众号:自由的小黑 中去讨论。
你懂了没?