03-Python 打包工具 setuptools setup.py 打包的文件

官方文档:https://setuptools.pypa.io/en/latest/userguide/datafiles.html

需要打包的文件

如果想要打包一些文件,通常通过setup函数的这些参数packagesinclude_package_data(其实就是MANIFEST.in文件)、exclude_package_datapackage_datadata\_files 来指定需要打包的文件。

使用 setpy.up 打包 包含的文件如下:

  • py_modulespackages 可以包含参数中所有 Python 源文件
  • ext_modulesorlibraries 可以包含参数中提到的所有 C 源文件
  • scripts 可以包含参数指定的脚本
  • package_datadata_files 可以包含参数指定的所有文件
  • setup.cfgsetup.py
  • 类似于readme的文件(如README、README.txt、 README.rst、README.md)
  • MANIFEST.in 中指定的所有文件

前置知识

python中的packages有两种,一种是包含 __init__.py 的文件夹(姑且叫做*普通package),一种是不含__init__.py 的文件夹(这是python3引入的Namespace Packages**命名空间包)。

packages,包含参数中所有 Python 文件,不包含子目录

packages 参数就是用来指示打包分发时需要包含的package,**type为list[str]**。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
project
├──setup.py
├──debug
│ └──debug.py
├──src
│ ├──__init__.py
│ ├──pack1
│ │ ├──__init__.py
│ │ ├──main.py
│ │ ├──config.txt
│ │ └──data
│ │ ├──main.py
│ │ └──a.dat
│ └──pack2
│ ├── a.json
│ └── b.jpg

其中setup.py文件内容为

1
2
from setuptools import setup
setup(packages=['src'])

运行python setup.py sdist --formats=zip 打包命令

1
2
├──src
│ ├──__init__.py

发现只打包了src和下面的__init__.py,pack1不见踪影。

说明packages参数时,不会递归的打包子package!只打包当前package!

  • 改为 setup(packages=['src','src.pack1','src.pack1.data']) 就可以了。

find_namespace_packages,find_packages 打包参数中的目录及子目录

但每次都这样写也太费时费力了。所以setuptools提供了两个函数find_namespace_packages,find_packages来快速找到所有的package。

  • 改为setup(packages=find_packages()) 发现没有打包data和debug文件夹!

是因为 find_packages 只会打包内含 __init__.py 的package,而data和debug文件夹正好没有__init__.py

  • 改为setup(packages=find_namespace_packages()) 就可以打包data和debug文件夹。

此外如果不想打包debug文件夹,可以给find_namespace_packages传递参数以指定在哪个文件夹下进行搜索,比如setup(packages=find_namespace_packages('src')),这样就不会打包debug文件夹。

上面这些例子中都没有包含非源码文件(如.dat和.txt文件),需要通过别的参数include_package_data(其实就是MANIFEST.in文件)、exclude_package_datapackage_data来打包非源码文件。

include_package_data 根据 MANIFEST.in 文件来打包分发库(常用)

include_package_data 是bool类型,默认值为True。当为True时,将根据MANIFEST.in文件来打包分发库

MANIFEST.in 需要放在和 setup.py 同级的顶级目录下,setuptools 会自动读取该文件。

MANIFEST.in 文件指定了一些语法规则,主要是用来打包非源码文件的,语法规则如下:

命令 描述
include pat1 pat2 … 添加与任何列出的模式匹配的所有 文件(文件必须作为相对于项目根目录的路径给出)
exclude pat1 pat2 … 删除与任何列出的模式匹配的所有 文件(文件必须作为相对于项目根目录的路径给出)
recursive-include dir-pattern pat1 pat2 … 递归dir-pattern及其子文件夹,添加与任何列出的模式匹配的目录下的所有 文件
recursive-exclude dir-pattern pat1 pat2 … 递归dir-pattern及其子文件夹,删除与任何列出的模式匹配的目录下的所有 文件
global-include pat1 pat2 … 在源树中的任何位置添加与任何列出的模式匹配的所有 文件
global-exclude pat1 pat2 … 删除源树中与任何列出的模式匹配的所有 文件
graft dir-pattern 添加匹配目录下的所有 文件夹
prune dir-pattern 删除匹配目录下的所有 文件夹

还是以之前的例子为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
project
├──setup.py
├──debug
│ └──debug.py
├──src
│ ├──__init__.py
│ ├──pack1
│ │ ├──__init__.py
│ │ ├──main.py
│ │ ├──config.txt
│ │ └──data
│ │ ├──main.py
│ │ └──a.dat
│ └──pack2
│ ├── a.json
│ └── b.jpg

MANIFEST.in 文件内容为:

1
2
3
4
5
6
7
recursive-include . *.txt *.dat # 递归遍历当前文件夹,找到符合*.dat、*.txt的文件
# 或者
include src/pack1/*.txt
include src/pack1/data/*.dat
include src/pack2/a.jso?

graft pack2 # 把 pack2 打包

package_data

除了通过 MANIFEST.in的方法来指定,还可以通过 package_data 参数来指定,建议还是统一用 MANIFEST.in文件的方式,免得造成不一致性。

1
2
3
# setup.py
from setuptools import setup
setup(package_data={'':['*.txt'],'src.pk1':['*.dat']} # 其中''表示所有文件夹下

exclude_package_data

顾名思义就是去除文件

1
exclude_package_data={'src.pk1':['*.txt']}

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