发布流程
打包
-
方式一:使用轮子(wheels)发布
这种方式发布的是编译好的包,因此安装会更快,是更推荐的做法。
# 1. 先安装wheel $ pip install wheel # 2.1 如果源码是纯Python而且同时支持2和3,则 $ python setup.py bdist_wheel --universal # 2.2 如果只支持特定版本或平台,则使用对应版本执行 $ python setup.py bdist_wheel
-
方式二:直接使用源码发布
这种方式发布的包在安装的时候需要临时编译,所以比较慢,但是安装包会比较小。
$ python setup.py sdist
准备PyPI账号
首先要有个账号:可以在这里注册。
然后写入~/.pypirc
:
[distutils]
index-servers=pypi
[pypi]
repository = https://upload.pypi.org/legacy/
username = <username>
;password = <password>
上传
推荐使用twine上传。
# 安装twine
$ pip install twine
# 上传打包好的文件
$ twine upload dist/*
scope
不像 NPM 那么强大,PyPI 并不支持 scope,所以给包取名字的时候,我们需要自己考虑命名冲突的问题。
PEP 420 允许给包名指定命名空间(Implicit Namespace Packages)。即使这样,也并没有限定账号,所以其实这个命名空间还是大家都可以用的,只是方便管理。这时,我们可以给自己的包名加上账号前缀作为命名空间,毕竟一般来说,不会有人在自己的包名前面加上别人的账号当前缀吧。
发布有命名空间的包步骤如下:
-
包名添加前缀,如
gera2ld-pyserve
。值得注意的是,PEP 503 中提出了包名规范化,会把包名中的特殊字符都替换成
-
再处理,而且在最新的 pip 中,包名中出现其他特殊字符会导致安装失败,所以我们使用-
来连接前缀。 -
文件路径结果增加一层命名空间层,如下:
▾ gera2ld/ # 注:这里不能有 __init__.py ▾ pyserve/ __init__.py
注意命名空间目录下不能有
__init__.py
。只有这样,才能多个包共用一个 namespace 互不影响。 -
修改
setup.py
,手动指定子包的位置:setup( name='gera2ld-pyserve', packages=['gera2ld.pyserve'], )
因为
gera2ld
目录下没有__init__.py
,setuptools.find_packages
无法自动找到子包,所以需要手动指定 packages 。 - 接下来就可以按上文所述的步骤正常发布和使用了。
第三方包管理工具
pip 是 Python 自带的包管理工具,它存在一些问题,早已被 Node.js、Rust 等语言的包管理工具超越,所以也涌现了一些新的包管理工具,学习了其他语言的长处,不过他们底层都是基于 pip 的,所以仍然会有一些限制。
Poetry 就是一个很好的第三方包管理工具,它可以自动创建 virtualenv,支持像 NPM 那样使用当前安装的环境执行脚本,发布版本。它使用了和 NPM 类似的配置方式,所有的项目配置都存在 pyproject.toml
中。
通过 Poetry,我们可以更简单地发布一个包:
-
更新
pyproject.toml
,升级版本号version
:$ poetry version 1.0.0 $ git add . $ git commit -m v1.0.0 $ git tag -m v1.0.0 v1.0.0
-
代码编译和打包:
$ poetry build
-
发布:
$ poetry publish