包装配送项目

本节介绍如何配置、打包和分发自己的Python项目的基础知识。它假定您已经熟悉 安装程序包 页。

这部分有 not 目的涵盖整个Python项目开发的最佳实践。例如,它不为版本控制、文档或测试提供指导或工具建议。

有关更多参考资料,请参见 Building and Distributing Packagessetuptools 但请注意,有些咨询内容可能已经过时。如果发生冲突,请参考《Python打包用户指南》中的建议。

包装和分发要求

  1. 首先,确保你已经完成了 requirements for installing packages .

  2. 安装“绳线” 1:

    pip install twine
    

    你需要这个来上传你的项目 distributionsPyPI (见 below

配置项目

初始文件

setup.py

最重要的文件是 setup.py 它存在于项目目录的根目录中。例如,请参见 setup.pyPyPA sample project .

setup.py 服务于两个主要功能:

  1. 它是配置项目各个方面的文件。的主要特征 setup.py 它包含一个全局 setup() 功能。此函数的关键字参数是如何定义项目的特定详细信息。最相关的论点在 the section below .

  2. 它是用于运行与打包任务相关的各种命令的命令行界面。要获取可用命令的列表,请运行 python setup.py --help-commands .

setup.cfg

setup.cfg 是包含选项默认值的ini文件 setup.py 命令。例如,请参见 setup.cfgPyPA sample project .

自述文件.rst/readme.md

所有项目都应该包含一个包含项目目标的自述文件。最常见的格式是 reStructuredText 具有“RST”扩展名,尽管这不是一项要求;多个变体 Markdown 也支持(请看 setup()long_description_content_type 争论)。

例如,请参见 README.mdPyPA sample project .

注解

项目使用 setuptools 0.6.27+具有标准自述文件 (README.rstREADME.txtREADME )默认情况下包含在源分发中。内置 distutils 库从Python3.7开始采用这种行为。此外, setuptools 36.4.0+包括 README.md 如果找到。如果您使用的是安装工具,则无需在 MANIFEST.in . 否则,将其包含为显式的。

MANIFEST.in

A MANIFEST.in 当需要打包不自动包含在源分发中的其他文件时需要。有关编写 MANIFEST.in 文件,包括默认情况下包含的内容的列表,请参见“:ref:using manifest.in”。

例如,请参见 MANIFEST.inPyPA sample project .

注解

MANIFEST.in 不影响二进制分布,如轮子。

LICENSE.txt

每个软件包都应该包含一个详细说明分发条款的许可证文件。在许多管辖区,没有明确许可证的软件包不能由版权持有人以外的任何人合法使用或分发。如果您不确定要选择哪个许可证,可以使用以下资源: GitHub's Choose a License 或者咨询律师。

例如,请参见 LICENSE.txtPyPA sample project .

<your package>

尽管这不是必需的,但最常见的做法是将您的Python模块和包包含在一个具有相同的顶级包中。 name 作为你的项目,或者非常接近的东西。

例如,请参见 sample 包含在 PyPA sample project .

setup()参数

如上所述,其主要特点是 setup.py 它包含一个全局 setup() 功能。此函数的关键字参数是如何定义项目的特定详细信息。

最相关的论点解释如下。给出的大部分代码片段都是从 setup.py 包含在 PyPA sample project .

名称

name='sample',

这是项目的名称,决定了项目在 PyPI . 每 PEP 508 ,有效的项目名称必须:

  • 仅由ASCII字母、数字、下划线组成 (_ )连字符 (- )和/或周期 (.

  • 以ASCII字母或数字开头和结尾。

项目名称的比较不区分大小写,并将任意长的下划线、连字符和/或句点视为相等。例如,如果注册名为 cool-stuff ,用户将可以下载它或使用以下任何拼写声明对它的依赖:

Cool-Stuff
cool.stuff
COOL_STUFF
CoOl__-.-__sTuFF

版本

version='1.2.0',

这是您项目的当前版本,允许您的用户确定他们是否有最新版本,并指示他们测试自己的软件所针对的特定版本。

版本显示在 PyPI 如果发布项目,则为每个版本。

选择版本控制方案 有关如何使用版本向用户传递兼容性信息的详细信息。

如果项目代码本身需要对版本进行运行时访问,最简单的方法是将版本保存在 setup.py 还有你的密码。如果您不想复制该值,有几种方法可以管理它。请参见“:ref:single sourcing the version”高级主题部分。

描述

description='A sample Python project',
long_description=long_description,
long_description_content_type='text/x-rst',

为你的项目做一个简短而详细的描述。

这些值将显示在 PyPI 如果发布项目。论 pypi.org ,用户界面显示 description 在灰色横幅和 long_description 在名为“项目说明”的部分中。

description 也显示在项目列表中。例如,它在https://pypi.org/search/等搜索结果页面中可见。Q=jupyter,趋势项目和新版本的首页列表,以及您在帐户配置文件中维护的项目列表(如https://pypi.org/user/jaraco/)。

A content type 可以用指定 long_description_content_type 参数,可以是 text/plaintext/x-rsttext/markdown ,对应无格式, reStructuredText (reST) 和吉特胡伯风味的降价方言 Markdown 分别。

网址

url='https://github.com/pypa/sampleproject',

为您的项目提供主页URL。

作者

author='The Python Packaging Authority',
author_email='pypa-dev@googlegroups.com',

提供作者的详细信息。

许可

license='MIT',

这个 license 参数不必指明发布包所依据的许可证,但如果需要,您可以选择这样做。如果您使用的是标准的、知名的许可证,那么您的主要指示可以也应该通过 classifiers 参数。所有主要的开源许可证都有分类器。

“许可证”参数通常用于表示与已知许可证的差异,或者包括您自己的唯一许可证。作为一般规则,使用标准的、众所周知的许可证是一个好主意,既可以避免混淆,也可以因为一些组织避免使用许可证未经批准的软件。

"Classifier" 对于以下值的一些示例: license .

分类器

classifiers=[
    # How mature is this project? Common values are
    #   3 - Alpha
    #   4 - Beta
    #   5 - Production/Stable
    'Development Status :: 3 - Alpha',

    # Indicate who your project is intended for
    'Intended Audience :: Developers',
    'Topic :: Software Development :: Build Tools',

    # Pick your license as you wish (should match "license" above)
     'License :: OSI Approved :: MIT License',

    # Specify the Python versions you support here. In particular, ensure
    # that you indicate whether you support Python 2, Python 3 or both.
    'Programming Language :: Python :: 2',
    'Programming Language :: Python :: 2.6',
    'Programming Language :: Python :: 2.7',
    'Programming Language :: Python :: 3',
    'Programming Language :: Python :: 3.2',
    'Programming Language :: Python :: 3.3',
    'Programming Language :: Python :: 3.4',
],

提供分类项目的分类器列表。有关完整的列表,请参阅https://pypi.org/classifiers/。

尽管分类器列表通常用于声明项目支持的Python版本,但此信息仅用于搜索和浏览Pypi上的项目,而不用于安装项目。要实际限制项目可以安装的Python版本,请使用 python_requires 争论。

关键词

keywords='sample setuptools development',

列出描述项目的关键字。

project_urls

project_urls={
    'Documentation': 'https://packaging.python.org/tutorials/distributing-packages/',
    'Funding': 'https://donate.pypi.org',
    'Say Thanks!': 'http://saythanks.io/to/example',
    'Source': 'https://github.com/pypa/sampleproject/',
    'Tracker': 'https://github.com/pypa/sampleproject/issues',
},

列出有关项目的其他相关URL。这是链接到bug追踪器、源存储库或支持包开发的位置。键的字符串是将在pypi上显示的确切文本。

包装

packages=find_packages(exclude=['contrib', 'docs', 'tests*']),

集合 packages 到所有列表 packages 在您的项目中,包括它们的子包、子包等,尽管包可以手动列出, setuptools.find_packages() 自动查找。使用 exclude 关键字参数,用于省略不打算发布和安装的包。

py_modules

py_modules=["six"],

如果项目包含任何不属于包的单个文件python模块,请设置 py_modules 到模块名称列表(减去 .py 扩展)以便 setuptools 了解他们。

install_requires

install_requires=['peppercorn'],

“Install_Requires”应用于指定项目最低限度需要运行的依赖项。当项目由安装时 pip ,这是用于安装其依赖项的规范。

有关使用“安装要求”的更多信息,请参阅 安装需要vs需求文件 .

python_requires

如果您的项目仅在特定的Python版本上运行,请设置 python_requires 对适当的 PEP 440 版本说明符字符串将阻止 pip 在其他Python版本上安装项目。例如,如果您的包仅用于python 3+,请编写:

python_requires='>=3',

如果您的包是针对python 3.3及更高版本的,但您还不愿意承诺对python 4的支持,请编写:

python_requires='~=3.3',

如果您的包是针对python 2.6、2.7以及从3.3开始的python 3的所有版本,请编写:

python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4',

等等。

注解

对此功能的支持相对较新。您的项目的源代码分发和轮子(请参见 打包您的项目 )必须使用至少24.2.0版的 setuptools 为了 python_requires 要识别的参数和生成的相应元数据。

此外,只有版本9.0.0和更高版本的 pip 认识到 python_requires 元数据。拥有PIP早期版本的用户将能够在任何Python版本上下载和安装项目,而不管项目是什么。 python_requires 价值观。

package_data

package_data={
    'sample': ['package_data.dat'],
},

通常,需要将其他文件安装到 package . 这些文件通常是与包的实现密切相关的数据,或者包含使用包的程序员可能感兴趣的文档的文本文件。这些文件称为“包数据”。

该值必须是从包名称到应复制到包中的相对路径名称列表的映射。路径被解释为相对于包含包的目录。

有关详细信息,请参阅 Including Data Filessetuptools docs .

data_files

data_files=[('my_data', ['data/data_file'])],

尽管正在配置 package_data 足以满足大多数需求,在某些情况下,您可能需要放置数据文件 外部 你的 packages . 这个 data_files 指令允许您这样做。如果您需要安装其他程序所使用的文件(可能不知道python包),那么它非常有用。

(directory, files) 序列中的pair指定安装目录和要在其中安装的文件。这个 directory 必须是相对路径(尽管这在将来可能会改变,请参见 wheel Issue #92 )它是相对于安装前缀(python的 sys.prefix 对于默认安装; site.USER_BASE 对于用户安装)。中的每个文件名 files 是相对于 setup.py 在项目源分发的顶部编写脚本。

有关详细信息,请参阅上的distutils部分 Installing Additional Files .

注解

当把包裹装成鸡蛋时, data_files 不支持。因此,如果您的项目使用 setuptools ,必须使用 pip 安装它。或者,如果必须使用 python setup.py ,然后你需要通过 --old-and-unmanageable 选择权。

脚本

虽然 setup() 支持 scripts 关键字用于指向预先制作好的脚本进行安装,建议使用实现跨平台兼容性的方法 console_scripts 入口点(见下文)。

entry_points

entry_points={
  ...
},

使用此关键字可以指定项目为项目或依赖的其他项目定义的任何命名入口点提供的任何插件。

有关详细信息,请参见 Dynamic Discovery of Services and Pluginssetuptools 博士学位。

最常用的入口点是“控制台脚本”(见下文)。

console_scripts
entry_points={
    'console_scripts': [
        'sample=sample:main',
    ],
},

使用“控制台脚本” entry points 注册脚本接口。然后,您可以让工具链处理将这些接口转换为实际脚本的工作。 2. 脚本将在安装 distribution .

有关详细信息,请参阅 Automatic Script Creationsetuptools docs .

选择版本控制方案

互操作性标准符合性

不同的python项目可以根据特定项目的需要使用不同的版本控制方案,但所有这些方案都需要符合 public version scheme 指定在 PEP 440 以便在工具和库(如 pipsetuptools .

以下是一些兼容版本号的示例:

1.2.0.dev1  # Development release
1.2.0a1     # Alpha Release
1.2.0b1     # Beta Release
1.2.0rc1    # Release Candidate
1.2.0       # Final Release
1.2.0.post1 # Post Release
15.10       # Date based release
23          # Serial release

为了进一步适应版本编号方法的历史变化, PEP 440 还定义了 version normalisation 它将不同版本号的不同拼写映射到标准化的规范形式。

方案选择

语义版本控制(首选)

对于新项目,建议的版本控制方案基于 Semantic Versioning 但采用了不同的方法来处理预发布和构建元数据。

语义版本化的本质是由三部分组成的major.minor.maintenance编号方案,其中项目作者递增:

  1. 主版本,当它们进行不兼容的API更改时,

  2. 次要版本,当它们以向后兼容的方式添加功能时,以及

  3. 当他们进行向后兼容的错误修复时的维护版本。

作为项目作者,采用这种方法允许用户利用 "compatible release" 说明符,其中 name ~= X.Y 至少需要X.Y版本,但也允许以后的版本与匹配的主版本相匹配。

采用语义版本控制的Python项目应遵守 Semantic Versioning 2.0.0 specification .

基于日期的版本控制

对于所有项目来说,语义版本化并不是一个合适的选择,例如那些具有定期的基于时间的发布周期的项目,以及在删除某个特性之前为许多发布提供警告的拒绝过程。

基于日期的版本控制的一个主要优点是,可以很容易地告诉您,一个特定版本的基本特性集的版本号是多少。

基于日期的项目的版本号通常采用year.month格式(例如, 12.0415.10

串行版本控制

这是最简单的版本控制方案,由单个数字组成,每个版本都递增。

虽然作为一个开发人员,串行版本控制非常容易管理,但是作为一个最终用户,它是最难跟踪的,因为串行版本号很少或没有关于API向后兼容性的信息。

混合方案

上述方案的组合是可能的。例如,一个项目可以将基于日期的版本控制与序列版本控制结合起来创建一个年份。序列编号方案可以很容易地传递一个发布的大概时间,但不会在一年内以其他方式承诺特定的发布周期。

预发布版本

无论基础版本方案如何,给定最终版本的预发布都可以发布为:

  • 零个或多个dev版本(以“.devn”后缀表示)

  • 零个或多个alpha版本(用“.an”后缀表示)

  • 零个或更多beta版本(以“.bn”后缀表示)

  • 零个或多个发布候选(以“.rcn”后缀表示)

pip 而其他现代的python包安装程序在决定要安装哪些版本的依赖项时,默认情况下会忽略预发布。

本地版本标识符

公共版本标识符设计为支持通过 PyPI . python的软件分发工具还支持 local version identifier 可用于标识不打算发布的本地开发构建,或由再分配程序维护的版本的修改变体。

本地版本标识符采用以下形式 <public version identifier>+<local version label> . 例如::

1.2.0.dev1+hg.5.b11e5e6f0b0b  # 5th VCS commmit since 1.2.0.dev1 release
1.2.1+fedora.4                # Package with downstream Fedora patches applied

在“发展模式”下工作

尽管不是必需的,但是在您处理项目时,通常以“可编辑”或“开发”模式本地安装项目。这允许在项目窗体中安装和编辑项目。

假设您在项目目录的根目录中,那么运行:

pip install -e .

虽然有些神秘, -e is short for --editable, and . 指的是当前的工作目录,所以它一起意味着在可编辑模式下安装当前目录(即您的项目)。这还将安装用“install_requires”声明的任何依赖项,以及用“console_scripts”声明的任何脚本。依赖项将以常规的不可编辑模式安装。

在可编辑模式下安装一些依赖项也是很常见的。例如,假设您的项目需要“foo”和“bar”,但您希望在可编辑模式下从VCS安装“bar”,那么您可以这样构造一个需求文件:

-e .
-e git+https://somerepo/bar.git#egg=bar

第一行是安装项目和任何依赖项。第二行重写“bar”依赖项,这样就可以从VCS而不是Pypi实现它。

但是,如果希望在可编辑模式下从本地目录安装“bar”,则需求文件应该如下所示,文件顶部的本地路径为:

-e /path/to/project/bar
-e .

否则,由于需求文件的安装顺序,依赖关系将从PYPI实现。有关需求文件的更多信息,请参见 Requirements File PIP文档中的部分。有关VCS安装的更多信息,请参阅 VCS Support PIP文档的部分。

最后,如果您根本不想安装任何依赖项,可以运行:

pip install -e . --no-deps

有关详细信息,请参阅 Development Mode 剖面图 setuptools docs .

打包您的项目

从一个 Package Index 喜欢 PyPI ,您需要创建一个 Distribution (又名“:term:package<distribution package>”)用于您的项目。

震源分布

至少,您应该创建一个 Source Distribution

python setup.py sdist

“源分发”是不建立的(即,它不是 Built Distribution ,并且在由PIP安装时需要一个构建步骤。即使发行版是纯Python(即不包含扩展),它仍然需要一个构建步骤来构建安装元数据 setup.py .

车轮

您还应该为项目创建一个轮子。轮子是 built package 无需经过“构建”过程即可安装。对于最终用户来说,安装车轮比从源分发版安装要快得多。

如果您的项目是纯Python(即不包含已编译的扩展),并且本机支持Python2和3,那么您将创建所谓的 *Universal Wheel* (see section below) .

如果您的项目是纯Python,但本机不支持Python2和3,那么您将创建一个 "Pure Python Wheel" (see section below) .

如果您的项目包含已编译的扩展名,那么您将创建一个称为 *Platform Wheel* (see section below) .

在为项目构建轮子之前,需要安装 wheel 包裹:

pip install wheel

万向轮

万向轮 是纯Python(即不包含编译扩展)并支持Python2和3的轮子。这是一个可以安装在任何地方的轮子 pip .

制造车轮:

python setup.py bdist_wheel --universal

也可以永久设置 --universal 标记 setup.cfg (例如,参见 sampleproject/setup.cfg ):

[bdist_wheel]
universal=1

只使用 --universal 设置,如果:

  1. 您的项目运行在python 2和3上,没有任何更改(即它不需要2to3)。

  2. 您的项目没有任何C扩展。

当心那个 bdist_wheel 如果使用设置不当,当前没有任何警告检查。

如果您的项目具有可选的C扩展,则建议不要发布通用车轮,因为PIP将首选车轮而不是源安装,并防止生成扩展的可能性。

纯python轮子

纯python轮子 不是“通用”的轮子是纯Python(即不包含已编译的扩展),但本机不支持Python2和3。

制造车轮:

python setup.py bdist_wheel

bdist_wheel 将检测到代码是纯Python,并构建一个名为wheel的轮子,以便在任何具有与构建wheel所用版本相同的主要版本(python 2或python 3)的Python安装上都可用。有关车轮文件命名的详细信息,请参见 PEP 425 .

如果您的代码同时支持python 2和3,但使用了不同的代码(例如, "2to3" )你可以跑 setup.py bdist_wheel 两次,一次使用python 2,一次使用python 3。这将为每个版本生成轮子。

平台车轮

平台车轮 是特定于特定平台(如Linux、MacOS或Windows)的控制盘,通常是由于包含编译的扩展。

制造车轮:

python setup.py bdist_wheel

bdist_wheel 将检测到代码不是纯Python,并构建一个名为wheel的轮子,使其仅在构建它的平台上可用。有关车轮文件命名的详细信息,请参见 PEP 425 .

注解

PyPI 目前支持Windows、MacOS和多发行版平台轮子的上载 manylinux1 阿比后者的详细信息在 PEP 513 .

将您的项目上载到pypi

当您运行创建分发的命令时,一个新目录 dist/ 是在项目的根目录下创建的。在这里您可以找到要上载的分发文件。

注解

只有在运行命令创建分发时,才会创建这些文件。这意味着,无论何时更改项目的源代码或 setup.py 文件,您需要重新生成这些文件,然后才能将更改分发到pypi。

注解

在发布主pypi repo之前,您可能更喜欢使用 PyPI test site 半定期清洗。见 使用testpypi 关于如何设置配置以使用它。

警告

在其他资源中,您可能会遇到使用 python setup.py registerpython setup.py upload . 这些注册和上载包的方法是 强烈反对 因为它可能在某些Python版本上使用纯文本HTTP或未经验证的HTTPS连接,从而允许在传输过程中截取您的用户名和密码。

小技巧

在pypi上使用的restructuredtext分析器是 not 斯芬克斯!此外,为了确保所有用户的安全,禁止或删除某些类型的URL和指令(例如 .. raw:: 指令)。 之前 尝试上载您的分发,您应该检查是否在 setup.py 有效。您可以按照 pypa/readme_renderer 工具。

创建帐户

首先,你需要一个 PyPI 用户帐户。您可以创建一个帐户 using the form on the PyPI website .

注解

如果要避免在上载时输入用户名和密码,可以创建 $HOME/.pypirc 使用您的用户名和密码的文件:

[pypi]
username = <username>
password = <password>

请注意,这将以明文形式存储您的密码。

上传您的发行版

一旦你有了一个帐户,你就可以把你的发行版上传到 PyPI 使用 twine .

上载版本的过程是相同的,无论项目是否已经存在于PYPI上-如果它还不存在,则在上载第一个版本时将自动创建。

对于第二个和后续版本,pypi只要求新版本的版本号不同于任何先前版本。

twine upload dist/*

通过导航到URL,可以查看包是否已成功上载 https://pypi.org/project/<sampleproject> 在哪里? sampleproject 是您上载的项目的名称。您的项目可能需要一两分钟才能出现在网站上。


1

根据您的平台,这可能需要根或管理员访问权限。 pip 目前正在考虑将此更改为 making user installs the default behavior .

2

具体来说,“控制台脚本”方法生成 .exe Windows上的文件,这是必需的,因为操作系统特殊情况 .exe 文件夹。脚本执行功能 PATHEXT 以及 Python Launcher for Windows 允许在许多情况下使用脚本,但不能全部使用。