Python 打包详解

2021-04-03 language python

之前介绍了如何通过 pip 安装包,主要是以用户的角度介绍,这里则从开发角度介绍如何打包、分发。

setup.py

这里直接以示例进行讲解,当前的目录结构如下。

$ tree
.
├── foobar
   ├── hello.py
   ├── __init__.py
   └── main.py
└── setup.py

1 directory, 4 files
$ cat foobar/hello.py
def hey():
    print("Hello World")
$ cat foobar/main.py
import hello

def main():
    hello.hey()
$ cat setup.py 
import setuptools

setuptools.setup(
    name="foobar",
    version="1.0.0",
    packages=setuptools.find_packages(exclude=["tests.*"]),
)

上述仅仅列举了必须的参数,详细的 setup() 函数参数可以参考 Packaging and distributing projects 中的介绍。其中的 find_packages() 会在当前目录搜索所有的 Python 模块 (带 __init__.py 的目录),然后打包成 egg 文件包。

如下是常用的命令。

------ 将源码打包
$ python3 setup.py sdist --format=zip,tar
------ 在 dist 目录下的发布包中可以执行如下命令安装
# pip install setup.py
# pip install foobar-1.0.0-py3-none-any.whl

默认会安装到 /usr/local/lib64/python3.6/site-packages 这个目录下。

build

Python3 中可以通过 build 模块编译,此时会依赖 pyproject.toml 这个配置文件,详细的格式可以参考 Declaring project metadata 中的介绍。

----- 安装build工具
pip3 install --upgrade build
----- 在源码目录下执行
python3 -m build

然后会在 dist 目录下生成 *.whl 二进制包以及 *.tar.gz 源码包。

示例

这里以 MySQL 的 Python 客户端为例,源码可以从 Github MySQLClient 下载,因为包含了 C 的编译,需要先下载依赖。

----- 对于Ubuntu/Debain环境
# apt-get install python3-dev default-libmysqlclient-dev pkg-config
----- 对于CentOS环境
# yum install python3-devel mysql-devel pkgconfig

然后通过上述的 python3 -m build 编译即可,注意,如果要通过 python3 setup.py build 编译需要增加 name verison 等字段,否则打出的包名会有问题。

常用命令

----- 查看帮助文档
$ python setup.py --help-commands
----- 执行编译命令
$ python setup.py build
----- 打包
$ python setup.py sdist
$ python setup.py bdist --format=zip   # 创建zip文件
$ python setup.py bdist --format=gztar # 创建tar.gz文件
$ python setup.py bdist_wininst        # Windows exe文件
$ python setup.py bdist_msi            # Windows msi文件,等价于 --format=msi
$ python setup.py bdist_rpm            # Linux rpm文件,等价于 --format=rpm
----- 基于打包文件安装
$ pip install dist/xxx.tar.gz
----- 卸载刚安装的包
$ pip uninstall xxx

----- 安装wheel模块
# pip install wheel
----- 分别打包.egg和.whl包
$ python setup.py bdist_egg
$ python setup.py bdist_wheel