目前最常用的打包工具为setuptools,介绍setuptools之前,我们先了解一下distutils
distutils 是python的一个标准库,是python官方开发的一个分发包工具,所有后续的打包工具,都是基于它开发的。
distutils 的核心是setup.py文件,是模块分发和安装的指导文件。
但是它无法定义包之间的依赖关系。
1. setuptools
它是distutils的升级版,扩展了很多功能,能够帮助开发者更好地创建和分发Python包,尤其是具有复杂依赖关系的包。
其通过添加一个基本的依赖系统以及许多相关功能,弥补了该缺陷。他还提供了自动包查询程序,用来自动获取包之间的依赖关系,并完成这些包的安装,大大降低了安装各种包的难度,使之更加方便。
功能亮点:
- 利用EasyInstall自动查找、下载、安装、升级依赖包
- 创建Python Eggs
- 包含包目录内的数据文件
- 自动包含包目录内的所有的包,而不用在setup.py中列举
- 自动包含包内和发布有关的所有相关文件,而不用创建一个MANIFEST.in文件
- 自动生成经过包装的脚本或Windows执行文件
- 支持Pyrex,即在可以setup.py中列出.pyx文件,而最终用户无须安装Pyrex
- 支持上传到PyPI 可以部署开发模式,使项目在sys.path中
- 用新命令或setup()参数扩展distutils,为多个项目发布/重用扩展
- 在项目setup()中简单声明entry points,创建可以自动发现扩展的应用和框架
2. 安装
# 一般 Python 安装会自带 setuptools,如果没有可以使用 pip 安装
$ pip install setuptools
# 更新,以下两种任选
$ python ez_setup.py –U setuptools
$ pip install -U setuptools
3. 两种打包方式
Python 包的分发可以分为源码包和二进制包两种
3.1 源码包
源码包安装的过程,是先解压,再编译,最后才安装,所以它是跨平台的,由于每次安装都要进行编译,相对二进包安装方式来说安装速度较慢。常见的格式有:zip、gztar、bztar、ztar、tar
打包命令:
python setup.py sdist --formats=gztar
–formats 可以指定打包格式,可以用逗号分隔,同时打包多个格式,如:–formats=gztar,zip
包的名称为 setup.py 中定义的 name, version以及指定的包格式
3.2 二进制包
二进制包的安装过程省去了编译的过程,直接进行解压安装,所以安装速度较源码包来说更快。由于不同平台的编译出来的包无法通用,所以在发布时,需事先编译好多个平台的包。常见格式有:egg、wheel
Egg 格式是由 setuptools 在 2004 年引入,而 Wheel 格式是由 PEP427 在 2012 年定义。Wheel 的出现是为了替代 Egg,它的本质是一个zip包,其现在被认为是 Python 的二进制包的标准格式
使用wheel打包之前,需要先安装wheel模块
# 安装
pip install wheel
# 打包
python setup.py bdist_wheel
执行成功后,目录下除了 dist 和 *.egg-info 目录外,还有一个 build 目录用于存储打包中间数据。
4. 最关键的setup.py文件如何编写
在目录 setup_demo 下新建安装文件 setup.py,然后创建包 my_demo 模拟要打包源码包:
.
├── my_demo
│ └── __init__.py
└── setup.py
setup.py文件内容如下:
from setuptools import setup
setup(
name='App', # 应用名
version='1.0.0', # 版本号
author = 'web3.0'
author_email = 'xxxx@qq.com'
packages=['my_demo'], # 包括在安装包内的 Python 包,此处表示my_demo目录下所有文件
description = '这是项目描述'
)
更多参数:
程序分类信息
classifiers
from setuptools import setup, find_packages
setup(
classifiers = [
# 发展时期,常见的如下
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
# 开发的目标用户
'Intended Audience :: Developers',
# 属于什么类型
'Topic :: Software Development :: Build Tools',
# 许可证信息
'License :: OSI Approved :: MIT License',
# 目标 Python 版本
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
]
)
文件的分发
from setuptools import setup, find_packages
setup(
name='App', # 应用名
version='1.0.0', # 版本号
author = 'web3.0',
author_email = 'xxxx@qq.com',
description = '这是项目描述',
package_dir={'': 'src'},
packages=find_packages('src'),
# 安装过程中,需要安装的静态文件,如配置文件、service文件、图片等
data_files=[
('', ['conf/*.conf']),
('/usr/lib/systemd/system/', ['bin/*.service']),
],
# 希望被打包的文件
package_data={
'':['*.txt'],
'bandwidth_reporter':['*.txt']
},
# 不打包某些文件
exclude_package_data={
'bandwidth_reporter':['*.txt']
}
)
### 依赖包下载安装
```python
from setuptools import setup, find_packages
setup(
name='App', # 应用名
version='1.0.0', # 版本号
author = 'web3.0',
author_email = 'xxxx@qq.com',
description = '这是项目描述',
package_dir={'': 'src'},
packages=find_packages('src'),
# 表明当前模块依赖哪些包,install_requires 在安装模块时会自动安装依赖包
install_requires=['docutils>=0.3'],
# setup.py 本身要依赖的包,这通常是为一些setuptools的插件准备的配置
# 这里列出的包,不会自动安装。
setup_requires=['pbr'],
# 仅在测试时需要使用的依赖,在正常发布的代码中是没有用的。
# 在执行python setup.py test时,可以自动安装这三个库,确保测试的正常运行。
tests_require=[
'pytest>=3.3.1',
'pytest-cov>=2.5.1',
],
# extras_require 不会自动安装依赖包,这里仅表示该模块会依赖这些包
# 但是这些包通常不会使用到,只有当你深度使用模块时,才会用到,这里需要你手动安装
extras_require={
'PDF': ["ReportLab>=1.2", "RXP"],
'reST': ["docutils>=0.3"],
}
)
安装环境的限制
有些库并不是在所以的 Python 版本中都适用的,若一个库安装在一个未兼容的 Python 环境中,理论上不应该在使用时才报错,而应该在安装过程就使其失败,提示禁止安装。
这样的功能,可以使用 python_requires 来实现。
setup(
...
python_requires='>=2.7, <=3',
)