前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >创建和发布 Python 包

创建和发布 Python 包

作者头像
老齐
发布2021-04-30 11:41:49
9300
发布2021-04-30 11:41:49
举报
文章被收录于专栏:老齐教室老齐教室

如果你和我一样,希望将编写的 Python 实用程序与同事共享,最好的方法是制作一个软件包:它很容易安装,而且不需要复制粘贴。

不过,如果对其中的方法不熟悉,可能会感到头痛。下面就分几步介绍创建 Python 包的方法,供大家参考。

基本结构

创建一个名为podsearch的目录,进入这个目录,并创建一个虚拟环境(关于虚拟环境的文章,请参阅《Python 虚拟环境》)

代码语言:javascript
复制
$ mkdir podsearch
$ cd podsearch
$ python3 -m venv env
$ . env/bin/activate

然后在此目录中创建一个文件__init__.py,并写入下述函数。

代码语言:javascript
复制
.
├── .gitignore
└── podsearch
    └── __init__.py
"""Let's find some podcasts!"""

 __version__ = "0.1.0"


 def search(name, count=5):
     """Search podcast by name."""
     raise NotImplementedError()

测试包

用传统的方法,比较麻烦,这里推荐一个工具:flit,它可以简化一切。安装它:

代码语言:javascript
复制
pip install flit

安装之后,执行如下操作:

代码语言:javascript
复制
$ flit init
Module name [podsearch]:
Author [Anton Zhiyanov]:
Author email [m@antonz.org]:
Home page [https://github.com/nalgeon/podsearch-py]:
Choose a license (see http://choosealicense.com/ for more info)
1. MIT - simple and permissive
2. Apache - explicitly grants patent rights
3. GPL - ensures that code based on this is shared with the same terms
4. Skip - choose a license later
Enter 1-4 [1]: 1

Written pyproject.toml; edit that file to add optional extra info.

在这里,用 flit 创建了pyproject.toml 文件,这是一个元数据文件,它具有将软件包发布到 PyPI 所需的一切配置。

当然,一定要在 TestPyPi](https://test.pypi.org/)(测试库)和 PyPI(主要的存储库)注册,这两个地方的账号是完全独立的,所以你需要两个。

~/.pypirc中设置对存储库的访问:

代码语言:javascript
复制
[distutils]
index-servers =
  pypi
  pypitest

[pypi]
username: nalgeon  # replace with your PyPI username

[pypitest]
repository: https://test.pypi.org/legacy/
username: nalgeon  # replace with your TestPyPI username

并将包发布到测试存储库:

代码语言:javascript
复制
$ flit publish --repository pypitest
Found 4 files tracked in git
...
Package is at https://test.pypi.org/project/podsearch/

搞定!可以在 TestPyPi 上获取该软件包。

公共包

把文件中的代码修改一下,让它真的有用。

代码语言:javascript
复制
# ...

SEARCH_URL = "https://itunes.apple.com/search"

@dataclass
class Podcast:
    """Podcast metadata."""

    id: str
    name: str
    author: str
    url: str
    feed: Optional[str] = None
    category: Optional[str] = None
    image: Optional[str] = None


def search(name: str, limit: int = 5) -> List[Podcast]:
    """Search podcast by name."""
    params = {"term": name, "limit": limit, "media": "podcast"}
    response = _get(url=SEARCH_URL, params=params)
    return _parse(response)

并发布到主存储库 PyPI 。

代码语言:javascript
复制
flit publish

搞定!

为了使软件包更易于使用,我建议你再多做点事情。

文档

没有人喜欢写文档。但是如果没有文档,别人不了解你的东西,所以添加README.md以及CHANGELOG.md.

  • README.md
  • CHANGELOG.md

readme.md添加到pyproject.toml,这样 PyPI 就会在这个包的页面上显示它:

代码语言:javascript
复制
description-file = "README.md"

指定所支持的最低 Python 版本:

代码语言:javascript
复制
requires-python = ">=3.7"

更新 __init__.py 中的版本,并通过flit publish发布这个包:

  • README.md
  • CHANGELOG.md

测试

下面关注格式化(black)、测试覆盖率(coverage)、代码质量(flake8pylintmccabe)和静态分析(mypy)等,通过tox来执行所有操作。

代码语言:javascript
复制
$ pip install black coverage flake8 mccabe mypy pylint pytest tox

tox.ini中创建 tox 配置

代码语言:javascript
复制
[tox]
isolated_build = True
envlist = py37,py38,py39

[testenv]
deps =
    black
    coverage
    flake8
    mccabe
    mypy
    pylint
    pytest
commands =
    black podsearch
    flake8 podsearch
    pylint podsearch
    mypy podsearch
    coverage erase
    coverage run --include=podsearch/* -m pytest -ra
    coverage report -m

tox.ini 进行所有的检测:

代码语言:javascript
复制
$ tox -e py39
...
py39 run-test: commands[0] | black podsearch
All done! ✨ ? ✨
...
py39 run-test: commands[2] | pylint podsearch
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
...
py39 run-test: commands[6] | coverage report -m
TOTAL 100%
...
py39: commands succeeded
congratulations :)

太好了!测试通过,覆盖率100%。

云构建

每个可靠的开源项目都会在每次提交后运行云测试,所以此处亦然。

用 GitHub Actions 构建项目,用Codecov 检查测试覆盖率,用 Code Climate检查代码质量。

必须注册Codecov和Code Climate(都支持GitHub登录),并在设置中启用包存储库。

之后,将GitHub Actions build config添加到.github/workflows/build.yml:

代码语言:javascript
复制
# ...
jobs:
    build:
        runs-on: ubuntu-latest
        strategy:
            matrix:
                python-version: [3.7, 3.8, 3.9]

        env:
            USING_COVERAGE: "3.9"

        steps:
            - name: Checkout sources
              uses: actions/checkout@v2

            - name: Set up Python
              uses: actions/setup-python@v2
              with:
                  python-version: $

            - name: Install dependencies
              run: |
                  python -m pip install --upgrade pip
                  python -m pip install black coverage flake8 flit mccabe mypy pylint pytest tox tox-gh-actions

            - name: Run tox
              run: |
                  python -m tox

            - name: Upload coverage to Codecov
              uses: codecov/codecov-action@v1
              if: contains(env.USING_COVERAGE, matrix.python-version)
              with:
                  fail_ci_if_error: true

build.yml

GitHub通过“tox”进行测试,就像我们前面所做的一样。tox-gh-actions 包 和USING_COVERAGE 设置确保tox使用与GitHub Actions相同的Python版本,正如strategy.matrix所要求的那样(参阅Hynek Schlawak中的说明。)

最后一步将测试覆盖发送到Codecov。Code Climate不需要单独的步骤—它自动发现存储库的更改。

现在提交、推送和享受这一成果。让每个人都可以享受这一成果 - 把徽章添加到' README.md ':

代码语言:javascript
复制
[![PyPI Version][pypi-image]][pypi-url]
[![Build Status][build-image]][build-url]
[![Code Coverage][coverage-image]][coverage-url]
[![Code Quality][quality-image]][quality-url]

...

<!-- Badges -->

[pypi-image]: https://img.shields.io/pypi/v/podsearch
[pypi-url]: https://pypi.org/project/podsearch/
[build-image]: https://github.com/nalgeon/podsearch-py/actions/workflows/build.yml/badge.svg
[build-url]: https://github.com/nalgeon/podsearch-py/actions/workflows/build.yml
[coverage-image]: https://codecov.io/gh/nalgeon/podsearch-py/branch/main/graph/badge.svg
[coverage-url]: https://codecov.io/gh/nalgeon/podsearch-py
[quality-image]: https://api.codeclimate.com/v1/badges/3130fa0ba3b7993fbf0a/maintainability
[quality-url]: https://codeclimate.com/github/nalgeon/podsearch-py

是不是很cool

任务自动化

tox很好,但对开发不是很方便。运行诸如pylint、coverage等单个命令会更快,但这些命令非常冗长,因此我们将把这些枯燥的东西自动化。

用 Makefile为频繁的操作创建简短的别名:

代码语言:javascript
复制
.DEFAULT_GOAL := help
.PHONY: coverage deps help lint push test

coverage:  ## Run tests with coverage
 coverage erase
 coverage run --include=podsearch/* -m pytest -ra
 coverage report -m

deps:  ## Install dependencies
 pip install black coverage flake8 mccabe mypy pylint pytest tox

lint:  ## Lint and static-check
 flake8 podsearch
 pylint podsearch
 mypy podsearch

push:  ## Push code with tags
 git push && git push --tags

test:  ## Run tests
 pytest -ra

Makefile

以下是我们的任务:

代码语言:javascript
复制
$ make help
Usage: make [task]

task                 help
------               ----
coverage             Run tests with coverage
deps                 Install dependencies
lint                 Lint and static-check
push                 Push code with tags
test                 Run tests
help                 Show help message

要使代码更简洁,请使用“make”调用来替换原始的build.yml步骤:

代码语言:javascript
复制
- name: Install dependencies
  run: |
      make deps

- name: Run tox
  run: |
      make tox

云发布

在GitHub可以运行flit publish。我们来创建一个单独的工作流:

代码语言:javascript
复制
name: publish

on:
    release:
        types: [created]

jobs:
    publish:
        runs-on: ubuntu-latest
        steps:
            - name: Checkout sources
              uses: actions/checkout@v2

            - name: Set up Python
              uses: actions/setup-python@v2
              with:
                  python-version: "3.9"

            - name: Install dependencies
              run: |
                  make deps

            - name: Publish to PyPi
              env:
                  FLIT_USERNAME: ${{ secrets.PYPI_USERNAME }}
                  FLIT_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
              run: |
                  make publish

publish.yml

PYPI_USERNAMEPYPI_PASSWORD放在存储库设置((Settings > Secrets > New repository secret)中。使用你的PyPi用户名和密码,或者使用 API token.

现在,只要创建一个新版本,GitHub就会自动发布这个包。

正确配置下面的文件,能让你发布的内容更漂亮:

  • pyproject.toml
  • tox.ini
  • Makefile
  • build.yml
  • publish.yml

参考文献

https://antonz.org/python-packaging/?continueFlag=27ecc1d264efd99fc7f058dae314b3d9

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老齐教室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本结构
  • 测试包
  • 公共包
  • 文档
  • 测试
  • 云构建
  • 任务自动化
  • 云发布
  • 参考文献
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档