Ch5 distributing your software

阅读量:

摘要

  1. setup.py 的历史
  2. Wheel 的格式
  3. 上传至 Pypi
  4. 软件的 entry point

setup.py 的历史

最早在 1998 年是 Python 标准库的一部分,在 distutils 中,通过 from distutils.core import setup。2000 年时 distutils 终止开发,setuptools 提供 setup 的支持。2013 年 3 月,setuptoolsdistribute 的团队以 setuptools 合并了代码库。另一个项目 distutils2 使用 setup.cfg 来进行 setup,以方便开发者更容易的设置参数。distlib 可能会替代 distutils

使用 setuptools,结合 setup.pysetup.cfg

# setup.py
import setuptools

setuptools.setup()

# setup.cfg
[metadata]
name = ...
author = ...
long_description = file: README.rst

另一个很有用的工具是 pbr(Python Build Reasonableness),功能为:

  1. 自动生成 Sphinx 文档
  2. 自动生成作者和修改日志文件基于 git 的历史
  3. 自动生成 git 的文件列表
  4. 基于 git 标签的版本控制

使用方法:

预先安装 pbr,之后 setuptools.setup(setup_requires=['pbr'], pbr=True)。代码库需要有 git 的标签。

Wheel 的格式

Wheel 文件与 zip 文件相同,但是使用不同的文件扩展名 whl

打包 whl 文件,python setup.py bdist_wheel

打包 Python2 和 Python3 均可用的 whlpython 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 testpypipython 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_resourcesstevedore 调用。

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。

#待整理笔记

反向链接

到头儿啦~

局部关系图