Ch5 distributing your software
摘要
-
setup.py
的历史 -
Wheel
的格式 - 上传至 Pypi
- 软件的 entry point
setup.py
的历史
最早在 1998 年是 Python 标准库的一部分,在 distutils
中,通过 from distutils.core import setup
。2000 年时 distutils
终止开发,setuptools
提供 setup
的支持。2013 年 3 月,setuptools
和 distribute
的团队以 setuptools
合并了代码库。另一个项目 distutils2
使用 setup.cfg
来进行 setup,以方便开发者更容易的设置参数。distlib
可能会替代 distutils
。
使用 setuptools
,结合 setup.py
和 setup.cfg
。
# setup.py
import setuptools
setuptools.setup()
# setup.cfg
[metadata]
name = ...
author = ...
long_description = file: README.rst
另一个很有用的工具是 pbr(Python Build Reasonableness)
,功能为:
- 自动生成
Sphinx
文档 - 自动生成作者和修改日志文件基于 git 的历史
- 自动生成 git 的文件列表
- 基于 git 标签的版本控制
使用方法:
预先安装 pbr
,之后 setuptools.setup(setup_requires=['pbr'], pbr=True)
。代码库需要有 git 的标签。
Wheel
的格式
Wheel
文件与 zip
文件相同,但是使用不同的文件扩展名 whl
。
打包 whl
文件,python setup.py bdist_wheel
。
打包 Python2 和 Python3 均可用的 whl
,python setup.py bdist_wheel --universal
。
打包 tar
文件,python setup.py sdist
。
上传至 Pypi
在测试服务器上注册项目,在项目文件夹中创建 .pypirc
文件
[distutils]
index-servers =
testpypi
[testpypi]
username = <username>
password = <password>
repository = https://testpypi.python.org/pypi
注册项目 python setup.py register -r testpypi
,上传项目 python setup.py sdist upload -r testpypi
或 python setup.py bdist_wheel upload -r testpypi
。当不使用 -r testpypi
时,会上传至 Pypi 的主服务器。
软件的 entry point
使用 epi(entry point inspector)
查看所有可用的 entry point,pip install entry-point-inspector
。使用命令 epi group list
列出所有 entry point group。其中 console_scripts
组允许直接在命令行中执行指定的函数。
使用 setup.py
安装。
setup(
...,
entry_points={
"console_scripts": [
"server = foobar.server:main",
"client = foobar.client:main"
]
}
)
使用 setup.cfg
安装。
[metadata]
...
[options.entry_points]
console_scripts =
ser = foobar.server:main
cli = foobar.client:main
使用
pip install .
时,会出现No Module named foobar
的错误。 使用python setup.py install
时,一切正常。 需要在文件夹中创建__init__.py
文件。
也可自定义 entry point group 之后使用 pkg_resources
或 stevedore
调用。
pkg_resources
import pkg_resources
for entry_point in pkg_resources.iter_entry_points('testgroup'):
entry_point.load()()
stevedore
from stevedore.extension import ExtensionManager
from stevedore.driver import DriverManager
extensions = ExtensionManager('testgroup', invoke_on_load=True)
for extension in extensions:
extension.obj
DriverManager('testgroup','cli',invoke_on_load=True)
DriverManager('testgroup','value',invoke_on_load=True)
ExtensionManager
调用自定义组中的所有 entry point,DriverManager
调用自定义组中指定的某一个 entry point。
#待整理笔记