OpenStack是使用setuptools工具来进行打包,不过为了满足OpenStack项目的需求,引入了一个辅助工具pbr来配合setuptools完成打包工作。
pbr (Python Build Reasonableness)
pbr是一个setuptools的扩展工具,被开发出来的主要目的是为了方便使用setuptools,其项目文档地址在OpenStack官网内:http://docs.openstack.org/developer/pbr/
pbr使用方式

import setuptools
setuptools.setup(setup_requires=['pbr'], pbr=True)
按照上面的方式就可以配置setuptools工具使用pbr来协助完成打包工作。这里setup_requires参数是setup函数在执行之前需要依赖的包的列表。这里依赖的包的功能可以理解为生成setup的实际参数。你可以看到,当使用pbr的时候,setup函数只有两个参数,然而实际上setuptools.setup函数实际上是disutils.core.setup函数,会接收任何参数,这些参数可以通过在调用时指定,也可以通过所依赖的扩展来生成(比如pbr)。

OpenStack社区为啥要开发pbr呢?
因为setuptools库使用起来还是有点麻烦,参数太多,而且直接通过指定setup函数参数的方法实在太不方便了。pbr就是为了方便而生的,它带了了如下的改进:
1.使用setup.cfg文件来提供包的元数据。这个是从disutils2学来的。
2.基于requirements.txt文件来实现自动依赖安装。requirements.txt文件中包含了一个项目所要依赖的库,这个文件的格式是和pip兼容的。
3.利用Sphinx实现文档自动化。
4.基于git history自动生成AUTHORS和ChangeLog文件。
5.针对git自动创建文件列表。
6.基于git tags的版本号管理。

setup.cfg和requirements.txt
setup.cfg
由于OpenStack项目都使用了setuptools和pbr来执行打包工作,因此项目的元数据都放在setup.cfg文件中。我们以keystone项目的setup.cfg文件为例来说明这个文件里一般会包含什么内容

[update_catalog]
domain = keystone
output_dir = keystone/locale
input_file = keystone/locale/keystone.pot

[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = keystone/locale/keystone.pot
copyright_holder = OpenStack Foundation
msgid_bugs_address = https://bugs.launchpad.net/keystone

NOTE(dstanek): Uncomment the [pbr] section below and remove the ext.apidoc

Sphinx extension when https://launchpad.net/bugs/1260495 is fixed.

[pbr] # pbr本身的配置
warnerrors = True
autodoc_tree_index_modules = True

[entry_points] # 指定入口点
console_scripts = # 指定要生成的可执行文件
keystone-all = keystone.cmd.all:main
keystone-manage = keystone.cmd.manage:main

下面是其他entry_points内容,主要用于指定不同功能的扩展,和打包无关

classifier这个参数是用来指定一个软件包的分类、许可证、允许运行的操作系统、允许运行的Python的版本的信息。这些信息是在一个叫trove的项目。关于Python和trove的关系,请参考http://stackoverflow.com/questions/9094220/trove-classifiers-definition。
你可以在PyPI上找到完整的classifier值列表,地址是:https://pypi.python.org/pypi?%3Aaction=list_classifiers。另外,你也可以通过setuptools的命令来获取这个列表,在项目根目录下执行:python setup.py register --list-classifiers。

requirements.txt
这个文件指定了一个项目依赖的包有哪些,并且支出了依赖的包的版本需求,keystone项目的requirements.txt:

The order of packages is significant, because pip processes them in the order

of appearance. Changing the order has an impact on the overall integration

process, which may cause wedges in the gate later.

pbr<2.0,>=0.11
WebOb>=1.2.3
eventlet>=0.17.4
greenlet>=0.3.2
PasteDeploy>=1.5.0
Paste
Routes!=2.0,>=1.12.3
cryptography>=0.8.2 # Apache-2.0
six>=1.9.0
SQLAlchemy<1.1.0,>=0.9.7
sqlalchemy-migrate>=0.9.6
stevedore>=1.5.0 # Apache-2.0
passlib
python-keystoneclient>=1.6.0
keystonemiddleware>=1.5.0
oslo.concurrency>=2.1.0 # Apache-2.0
oslo.config>=1.11.0 # Apache-2.0
oslo.messaging!=1.12.0,>=1.8.0 # Apache-2.0
oslo.db>=1.10.0 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0
oslo.log>=1.2.0 # Apache-2.0
oslo.middleware!=2.0.0,>=1.2.0 # Apache-2.0
oslo.policy>=0.5.0 # Apache-2.0
oslo.serialization>=1.4.0 # Apache-2.0
oslo.service>=0.1.0 # Apache-2.0
oslo.utils>=1.6.0 # Apache-2.0
oauthlib>=0.6
pysaml2>=2.4.0
dogpile.cache>=0.5.3
jsonschema!=2.5.0,<3.0.0,>=2.0.0
pycadf>=0.8.0
msgpack-python>=0.4.0

软件包归档格式
Python的软件包一开始是没有官方的标准分发格式的。比如Java有jar包或者war包作为分发格式,Python则什么都没有。后来不同的工具都开始引入一些比较通用的归档格式。比如,setuptools引入了Egg格式。但是,这些都不是官方支持的,存在元数据和包结构彼此不兼容的问题。因此,为了解决这个问题,PEP 427定义了新的分发包标准,名为Wheel。目前pip和setuptools工具都支持Wheel格式。这里我们简单总结一下常用的分发格式:

•tar.gz格式:这个就是标准压缩格式,里面包含了项目元数据和代码,可以使用python setup.py sdist命令生成。
•.egg格式:这个本质上也是一个压缩文件,只是扩展名换了,里面也包含了项目元数据以及源代码。这个格式由setuptools项目引入。可以通过命令python setup.py bdist_egg命令生成。
•.whl格式:这个是Wheel包,也是一个压缩文件,只是扩展名换了,里面也包含了项目元数据和代码,还支持免安装直接运行。whl分发包内的元数据和egg包是有些不同的。这个格式是由PEP 427引入的。可以通过命令python setup.py bdist_wheel生成。

.egg-info和.dist-info目录
如果你到系统中安装Python库的路径下看看,就能看到很多名称以.egg-info或者以.dist-info结尾的目录。这些目录的内容就是这个库的元数据,是从库的分发包中拷贝出来的。其中.egg-info类型的目录来自于Egg格式的分发包,.dist-info类型的目录来自于Wheel格式的分发包。

软件包的安装
安装工具
上面已经提到了,setuptools项目提供了一个软件包安装工具esay_install。easy_install支持从软件归档文件中或者从PyPI上安装软件包,不过这个工具并不好用,比如缺少卸载功能等,因此并不流行,现在更多的都是使用pip工具。
pip项目提供了很好的软件包安装方式,并且已经被包含到Python 3.4中,可以从PyPI、tarball或者Wheel归档中安装和卸载软件按包。
关于pip常见的用法(pip install, pip uninstall, pip search, ...)。

安装路径
软件包的安装路径依赖于操作系统、Python版本和安装方式。
在Debian系的系统上(比如Ubuntu)
使用apt-get install从系统软件源安装
Python 2.7: /usr/lib/python2.7/dist-packages
Python 3.4: /usr/lib/python3.4/dist-packages

使用pip install命令安装
Python 2.7: /usr/local/lib/python2.7/dist-packages
Python 3.4: /usr/local/lib/python3.4/dist-packages

在virtualenv中使用pip install安装
Python 2.7: lib/python2.7/site-packages
Python 3.4: lib/python3.4/site-packages

在CentOS系的系统上

使用yum install命令安装

Python 2.7: /usr/lib/python2.7/site-packages

以开发模式安装
pip的安装命令可以使用-e选项,用来从本地代码目录或者版本库URL来安装一个开发版本的库。采用这种方式的时候,在安装目录下只会创建一个包含软件包信息的文件,真正的代码不会安装到系统目录下。

05-11 22:00