03-Python 打包工具 setuptools setup.py 使用

使用 setup.py 的方法打包有三种方式:

  • 使用命令行参数指定,一个一个将参数传递进去(极不推荐)。
  • 在 setup.py 中的 setup 函数中指定(推荐使用)。
  • 使用 pbr ,在 setup.cfg 中指定(易于管理,更推荐)。

python库的打包分发方式有两种:

  • 源码包source dist(简称sdist)。
    • *.tar.gz,安装使用 pip install *.tar.gz
  • 二进制包binary dist(简称bdist)。
    • *.whl*.egg,安装使用 pip install *.whlpip install *.egg

setup.py 命令

先看 setup.py 工具的帮助信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
python setup.py --help-commands

Standard commands:
build build everything needed to install
build_py "build" pure Python modules (copy to build directory)
build_ext build C/C++ extensions (compile/link to build directory)
build_clib build C/C++ libraries used by Python extensions
build_scripts "build" scripts (copy and fixup #! line)
clean clean up temporary files from 'build' command
install install everything from build directory
install_lib install all Python modules (extensions and pure Python)
install_headers install C/C++ header files
install_scripts install scripts (Python or otherwise)
install_data install data files
sdist create a source distribution (tarball, zip file, etc.)
register register the distribution with the Python package index
bdist create a built (binary) distribution
bdist_dumb create a "dumb" built distribution
bdist_rpm create an RPM distribution
bdist_wininst create an executable installer for MS Windows
check perform some checks on the package
upload upload binary package to PyPI

Extra commands:
bdist_wheel create a wheel distribution
alias define a shortcut to invoke one or more commands
bdist_egg create an "egg" distribution
develop install package in 'development mode'
dist_info create a .dist-info directory
easy_install Find/get/install Python packages
egg_info create a distribution's .egg-info directory
install_egg_info Install an .egg-info directory for the package
rotate delete older distributions, keeping N newest files
saveopts save supplied options to setup.cfg or other config file
setopt set an option in setup.cfg or another config file
test run unit tests after in-place build (deprecated)
upload_docs Upload documentation to sites other than PyPi such as devpi
ptr run unit tests after in-place build (deprecated)
pytest run unit tests after in-place build (deprecated)
isort Run isort on modules registered in setuptools
flake8 Run Flake8 on modules registered in setup.py

usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
or: setup.py --help [cmd1 cmd2 ...]
or: setup.py --help-commands
or: setup.py cmd --help

源码包 sdist

源码包sdist就是我们熟悉的 .zip.tar.gz 等后缀文件。就是一个压缩包,里面包含了所需要的的所有源码文件以及一些静态文件(txt文本、css、图片等)。

源码包打包

打包命令

1
python setup.py sdist --formats=gztar

参数

  • --formats 参数用来指定压缩格式,若不指定format格式,那么 sdist 将根据当前平台创建默认格式。可用格式为:

    格式 描述 注意
    zip 压缩档(.zip) zip 格式需要你事先已安装相应的模块:zip程序或zipfile模块(已成为Python的标准库)
    gztar gzip 压缩的 tar 文件(.tar.gz)
    bztar bzip2格式的tar 文件(.tar.bz2)
    xztar xz 的tar 文件(.tar.xz) 在版本3.5中才添加了对 xztar 格式的支持
    ztar 压缩的tar文件(.tar.Z) ztar 格式正在弃用,请尽量不要使用
    tar tar文件(.tar)
  • --owner=root --group=root:默认归档文件归创建者所有,如果您希望归档文件的所有文件归root拥有,可以使用此参数。

使用 sdist 将根据当前平台创建默认格式的存档。在类 Unix 平台上,将创建后缀后为 .tar.gz 的 gzip 压缩的tar文件分发包,而在Windows上为 ZIP 文件。

执行完该命令,我们可以看到文件夹下多了几个文件夹:

  • dist文件夹(包含压缩源码的分发包)
  • egg-info文件夹(中间临时配置信息)。

源码包安装

安装源码包有两种方法,先解压缩源码包,或者直接安装源码包。

  • 先解压缩源码包,再执行setup.py

    1
    2
    3
    4
    5
    6
    7
    python setup.py install  # 如果报过期的错,可以看后面的报错处理
    # 等价于
    python setup.py build
    python setup.py install

    # python setup.py install 包括两步:python setup.py build 和 python setup.py install。
    # 这两步可分开执行,也可只执行python setup.py install, 因为python setup.py install总是会先build后install.
  • 直接pip安装源码包

    1
    2
    $ pip install xxx.zip 
    $ pip install xxx.tar.gz

如果是开发阶段,可以用下面两个命令,该命令不会真正的安装包,而是在系统环境中创建一个软链接指向包实际所在目录。 这样在修改包之后不用再安装就能生效,便于调试

1
2
3
pip install -e .
# 等价于
python setup.py develop

二进制包 bdist

python目前主流的二进制包格式是wheel(.whl后缀),它的前身是egg。wheel本质也还是一个压缩包,可以像像zip一样解压缩。

与源码包相比,二进制包的特点是不用再编译,也就是安装更快! 在使用wheel之前,需要先安装wheel:$ pip install wheel

二进制包打包

语法

1
python setup.py bdist --formats=rpm

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 构建 linux 下的安装包:rpm 安装包。只能在 linux 下构建,也只能在 linux 下安装。下面两个命令等价
python setup.py bdist --formats=rpm # 创建 rpm 包
python setup.py build_rpm # 创建 rpm 包


# 构建 windows 下的安装包: exe 二进制软件包。只能在 windows 下构建,也只能在 windows 下安装。
python setup.py bdist_wininst # 创建"*.exe"的文件
python setup.py bdist_msi # 创建"*.msi"的文件
python setup.py bdist --format=msi # 同样是创建"*.msi"的文件


# 创建 egg wheel 格式的包
python setup.py bdist_egg # 打 *.egg 的包
python setup.py bdist_wheel # 打 *.whl 的包,在使用wheel之前,需要先安装wheel。

二进制包安装

直接pip就可以了

1
pip install xxx.whl

setup.py 总结

上面我们讲述了python打包分发的两种方法,很容易发现整个打包过程最重要的就是setup.py,它指定了重要的配置信息。

正常情况下,我们都是通过以上构建的源码包或者二进制包进行模块的安装。

setup.py 的文件的要求可以看另一篇博客。

发布包到 PyPi

通过上面的学习,你一定已经学会了如何打包自己的项目,若你觉得自己开发的模块非常不错,想要 share 给其他人使用,你可以将其上传到 PyPi (Python Package Index)上,它是 Python 官方维护的第三方包仓库,用于统一存储和管理开发者发布的 Python 包。

如果要发布自己的包,需要先到 pypi 上注册账号。然后创建 ~/.pypirc 文件,此文件中配置 PyPI 访问地址和账号。如的.pypirc文件内容请根据自己的账号来修改。

典型的 .pypirc 文件

1
2
3
4
5
6
[distutils]
index-servers = pypi

[pypi]
username:xxx
password:xxx

然后使用这条命令进行信息注册,完成后,你可以在 PyPi 上看到项目信息。

1
$ python setup.py register

注册完了后,你还要上传源码包,别人才使用下载安装

1
$ python setup.py upload

或者也可以使用 twine 工具注册上传,它是一个专门用于与 pypi 进行交互的工具,详情可以参考官网:https://www.ctolib.com/twine.html,这里不详细讲了。

打包辅助神器 PBR

pbr 是 setuptools 的辅助工具,最初是为 OpenStack 开发https://launchpad.net/pbr,基于d2to1

pbr 会读取和过滤 setup.cfg 中的数据,然后将解析后的数据提供给 setup.py 作为参数。包含如下功能:

  1. 从 git 中获取 Version、AUTHORS 和 ChangeLog 信息。

  2. Sphinx Autodoc。pbr 会扫描 project,找到所有模块,生成 stub files。

  3. Requirements。pbr 会读取 requirements.txt,生成 setup 函数需要的 install_requires/tests_require/dependency_links

    这里需要注意,在 requirements.txt 文件的头部可以使用:--index https://pypi.python.org/simple/,这一行把一个抽象的依赖声明如 requests==1.2.0 转变为一个具体的依赖声明 requests 1.2.0 from pypi.python.org/simple/

  4. long_description。从 README.rst, README.txt or README file 中生成 long_description 参数。

使用 pbr

  1. 需要在 setup.py 配置,文件内容:
1
2
3
4
5
6
from setuptools import setup

setup(
setup_requires=['pbr'],
pbr=True,
)
  1. 编写setup.cfg文件,一个示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # setup.cfg;
    [metadata]
    name = hellokpg
    version = 1.0
    author = xxx
    long_description = file: Readme.md # 从文件中读取
    license = MIT
    url = https://github.com/user/repo
    classifiers = # PyPI的分类,类似于标签,所有条目见 https://pypi.org/pypi?%3Aaction=list_classifiers
    Development Status :: 3 - Alpha
    Programming Language :: Python :: 3

    [options]
    packages = find: # 自动搜索存在__init__.py的文件夹作为包
    install_requires = # 依赖,pip安装时靠的就是这个而不是requirements.txt
    requests

    [options.entry_points]
    console_scripts =
    pyhello = hello.__main__:main

使用setup.cfg而不是setup.py的理由是,前者是声明式的配置文件,后者是实际的python代码,可能不安全。setuptools的文档中推荐从setup.py迁移到setup.cfg。 其实未来应该会使用pyproject.toml,但是现在setuptools不支持将它代替setup.cfg,只能代替setup.py,所以就没什么用,有个issue讨论但是没有ETA。

报错

install 过期 setup.py install is deprecated

详细报错如下:

1
2
3
4
5
6
7
8
9
10
11
$ python setup.py install

/opt/conda/lib/python3.7/site-packages/setuptools/config/setupcfg.py:516: SetuptoolsDeprecationWarning: The license_file parameter is deprecated, use license_files instead.
warnings.warn(msg, warning_class)
running install
/opt/conda/lib/python3.7/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
setuptools.SetuptoolsDeprecationWarning,
/opt/conda/lib/python3.7/site-packages/setuptools/command/easy_install.py:147: EasyInstallDeprecationWarning: easy_install command is deprecated. Use build and pip and other standards-based tools.
EasyInstallDeprecationWarning,
running bdist_egg
Aborting implicit building of eggs. Use `pip install .` to install from source.

参考:https://answers.ros.org/question/396439/setuptoolsdeprecationwarning-setuppy-install-is-deprecated-use-build-and-pip-and-other-standards-based-tools/

原因:版本太新了。

解决办法

1
pip install setuptools==58.2.0

Reference


03-Python 打包工具 setuptools setup.py 使用
https://flepeng.github.io/021-Python-13-pip、包管理-02-打包工具-setuptools-03-Python-打包工具-setuptools-setup-py-使用/
作者
Lepeng
发布于
2021年7月31日
许可协议