作者以 SciTime 项目(一个对算法训练时间进行估计的包)的发布为例,详细解释了发布的每个步骤。
注意:本文假设你在 GitHub 上已经有一个想要打包和发布的项目。
第 0 步:获取项目许可证
在做其他事之前,由于你的项目要开源,因此应该有一个许可证。获取哪种许可证取决于项目包的使用方式。开源项目中一些常见许可证有 MIT 或 BSD。
要在项目中添加许可证,只需参照以下链接中的步骤,将 LICENSE 文件添加到项目库中的根目录即可:https://help.github.com/en/articles/adding-a-license-to-a-repository
第 1 步:让你的代码准备就绪
要将项目进行打包,你需要做一些预备工作:
让你的项目结构正确就位。通常情况下,项目库的根目录包含一个以项目名称命名的文件夹,项目的核心代码应该位于此文件夹中。在这个文件夹之外是运行和构建包(测试、文档等)所需的其他代码。
核心文件夹应包括一个(或多个)模块和一个 __init__.py 文件,该文件包含你希望让终端用户访问的类/函数。此文件还可以包含包的版本,以便于终端用户访问。
理想情况下,应使用 logging 包来设置合理的日志记录系统(而不是用 prints 输出)。
理想情况下,应将你的核心代码分配到一个或多个类中。
- from .estimate import Estimator
以__init__.py 为例,如果 Estimator 是终端用户将会访问的类(该类在 estimate.py 文件中定义)
- import logging
- class LogMixin(object):
- @property
- def logger(self):
- name = '.'.join([self.__module__, self.__class__.__name__])
- FORMAT = '%(name)s:%(levelname)s:%(message)s'
- logging.basicConfig(format=FORMAT, level=logging.DEBUG)
- logger = logging.getLogger(name)
- return logger
以日志系统为例:LogMixin 类可以在其他任何类中使用
第 2 步:使用打包工具创建 setup.py
在你的项目有了一套结构之后,你应该在项目库的根目录下添加 setup.py 文件。这有助于所有发布和版本维护过程的自动化。以下是 setup.py 的例子
- from setuptools import setup
- from os import path
- DIR = path.dirname(path.abspath(__file__))
- INSTALL_PACKAGES = open(path.join(DIR, 'requirements.txt')).read().splitlines()
- with open(path.join(DIR, 'README.md')) as f:
- README = f.read()
- setup(
- name='scitime',
- packages=['scitime'],
- description="Training time estimator for scikit-learn algorithms",
- long_description=README,
- long_description_content_type='text/markdown',
- install_requires=INSTALL_PACKAGES,
- version='0.0.2',
- url='http://github.com/nathan-toubiana/scitime',
- author='Gabriel Lerner & Nathan Toubiana',
- author_email='toubiana.nathan@gmail.com',
- keywords=['machine-learning', 'scikit-learn', 'training-time'],
- tests_require=[
- 'pytest',
- 'pytest-cov',
- 'pytest-sugar'
- ],
- package_data={
- # include json and pkl files
- '': ['*.json', 'modelsscitime_data.py
- */setup.py
.coveragerc 文件示例
第 4 步:标准化语法和代码风格
你还需要确保你的代码遵循 PEP8 准则(即具有标准样式并且语法正确)。同样,有很多工具可以帮助你解决。这里我们用了 flake8。
第 5 步:创建一个合理的文档
现在你的项目已经测试过了,结构也很好了,是时候添加一个合理的文档。首先是要有一个好的 readme 文件,它会在你的 Github 项目库的根目录上显示。完成后,加上以下几点会更好:
Pull 请求和 issue 模板:当创建新的 Pull 请求或 issue 时,这些文件可以根据你的需求给你的描述提供模板。
贡献指南(contribution guide)。应该在贡献指南中简单地说明你希望外部用户如何协助你改进这个包。
由于 readme 文件应该相当综合,因此通常会有一个更详细的文档。你可以用 sphinx 来完成,然后在 readthedocs 上管理文档。与文档相关的文件通常放在 docs/文件夹中。
包含标签和说明的项目库示例
第 6 步:创建持续集成
此时,你的项目离发布就绪不远了。但是,在每次提交之后,必须更新文档、运行测试以及检查样式和覆盖率似乎有点难以应付。幸运的是,持续集成(CI)可以帮助你完成。你可以在每次提交之后使用 GitHub 的 webhook 来自动执行所有的这些操作。以下是我们在 SciTime 中使用的一套 CI 工具:
对于运行测试,我们使用了 travis ci 和 appveyor(用于 Windows 平台上的测试)。对于 Travis CI,除了在项目库上设置 webhook 之外,你还必须创建一个.travis.yml 文件,在该文件中,你不仅可以运行测试,还可以上传更新的覆盖率输出以及检查样式和格式。通过创建 appveyor.yml 文件,appveyor 也可以这样做。
codecov 和 readthdocs 也有专用的 webhook
- language: python
- python:
- - "3.6"
- # command to install dependencies
- install:
- - pip install -r requirements.txt
- - pip install flake8
- - pip install pytest-cov
- - pip install codecov
- # command to run tests
- script:
- - python -m pytest --cov=scitime
- - ./build_tools/flake_diff.sh
- after_success:
- - codecov
.travis.yml 文件的示例:请注意,每次提交,测试都需要与检查测试覆盖率一起进行。但还有一个 flake8 检查
- environment:
- matrix:
- - PYTHON: "C:\\Python36-x64"
- install:
- # We need wheel installed to build wheels
- - "%PYTHON%\\python.exe -m pip install -r requirements.txt"
- - "%PYTHON%\\python.exe -m pip install pytest==3.2.1"
- build: off
- test_script:
- - "%PYTHON%\\python.exe -m pytest"
appveyor.yml 文件示例:这里我们只运行测试
这将使更新项目库的整个过程更加容易。
集成 webhook 的提交历史记录示例
第 7 步:创建你的第一个 release 和 publication
此时,你即将发布的包应与以下类似:
- your_package/
- __init__.py
- your_module.py
- docs/
- tests/
- setup.py
- travis.yml
- appveyor.yml
- .coveragerc
- .codecov.yml
- README.md
- LICENSE
- .github/
- CODE_OF_CONDUCT.md
- CONTRIBUTING.md
- PULL_REQUEST_TEMPLATE.md
- ISSUE_TEMPLATE/
现在可以发布了!首先要做的是在 GitHub 上创建你的第一个 release——这是为了在给定的时间点跟踪项目的状态,每次版本更改时都需要创建新的 release。
完成后,唯一要做的就是发布包。发布 python 包最常见的平台是 PyPI 和 Conda。以下我们将描述如何用两者发布:
- 对于 PyPI,首先需要创建一个帐户,然后用 twine 执行一些步骤:https://realpython.com/pypi-publish-python-package/。这应该相当简单,而且 Pypi 还提供了一个可以在实际部署之前使用的测试环境。PyPI 总体上包括创建源代码(python setup.py sdist)并使用 twine(twine upload dist/*)来上传。完成后,应该有一个与你的包对应的 PyPI 页面,并且任何人都应该能够通过运行 pip 命令来安装你的包。
- 对于 Conda,我们推荐通过 conda forge 来发布你的包,conda forge 是一个社区,帮助你通过 conda 渠道发布和维护包。你可以按照以下步骤将包添加到社区:https://conda-forge.org/#add_recipe,然后你会被添加到 conda forge Github 组织中,并能够非常轻松地维护你的包,然后任何人都可以通过运行 conda 命令来安装你的包。
完成!
现在,你的包应该已经发出去,并且任何人都可以使用了!虽然大部分工作都完成了,但是你仍然需要维护你的项目,你需要进行一些更新:这大体上意味着每次进行重大更改时都要更改版本,创建新的 release,并再次执行第 7 步。