3. 编写设置脚本的配置文件

通常,在 事前 就写出构建发布包所需的一切是不可能的:你可能需要从用户或者用户的系统获取一些信息,才能继续下去。 只要这些信息相当简单 —— 例如一个用于搜索 C 头文件或库的目录列表 —— 那么提供配置文件 setup.cfg 供用户配置就是一个低成本且方便的解决方式。 配置文件还允许你为任何命令选项提供默认值,而安装器可以通过命令行或编辑配置文件来覆盖这些默认值。

安装配置文件是在安装脚本和安装脚本命令行之间一个适当的折衷方式 --- 安装脚本在理想情况下应当不受安装者的控制 1 --- 而安装脚本命令行则在你的控制范围之外且完全取决于安装者的选择。 实际上,setup.cfg (以及目标系统上的其他任何 Distutils 配置文件) 是在配置脚本之后、命令行之前被处理。 这导致了几个有用的后果:

  • 安装者可以通过编辑 setup.cfg 来覆盖你放在 setup.py 中的配置

  • 你可以为无法在 setup.py 中方便设置的选项提供非标准的默认值

  • 安装者可以使用 setup.py 的命令行选项来覆盖 setup.cfg 中的一切

配置文件的基本语法很简单:

[command]
option=value
...

其中 command 是一个 Distutils 命令 (例如 build_py, install),而 option 是该命令所支持的某个选项。 可以为每个命令提供任意数量的选项,并且可以在文件中包括任意数量的命令组。 空白行会被忽略,以一个 '#' 开始的注释行也是如此。 长选项值可以简单地通过缩进后续行的方式被拆分为多行。

你可以用通用的 --help 选项找出特定命令所支持的选项列表,例如

$ python setup.py --help build_ext
[...]
Options for 'build_ext' command:
  --build-lib (-b)     directory for compiled extension modules
  --build-temp (-t)    directory for temporary files (build by-products)
  --inplace (-i)       ignore build-lib and put compiled extensions into the
                       source directory alongside your pure Python modules
  --include-dirs (-I)  list of directories to search for header files
  --define (-D)        C preprocessor macros to define
  --undef (-U)         C preprocessor macros to undefine
  --swig-opts          list of SWIG command line options
[...]

请注意在命令行中拼写为 --foo-bar 的选项在配置文件中会拼写为 foo_bar

例如,假设你希望你的扩展在“原地”构建 --- 就是说你有一个扩展 pkg.ext,你希望编译出的扩展文件 (例如在 Unix 上为 ext.so) 放在与你的纯 Python 模块 pkg.mod1pkg.mod2 相同的源目录中。 你总是可以在命令行中使用 --inplace 选项来确保这一点:

python setup.py build_ext --inplace

但是这要求你总是显式地指定 build_ext 命令,并且记得提供 --inplace。 一个更容易的方式是通过将其编码在此发布包的配置文件 setup.cfg 中,“设置并忘记”该选项。

[build_ext]
inplace=1

这将影响此模块发布包的所有构建,不论你是否显式指定 build_ext。 如果你在你的源发布包中包括了 setup.cfg,它还将影响最终用户的构建 --- 对此选项来说这可能不是个好主意,因为总是原地构建扩展会破坏模块发布包的安装。 不过在某些特殊情况下,模块是在其安装目录中被构建的,因此这可能会是个有用的功能。 (但是,发布预期在其安装目录中被构建的扩展几乎总是一个坏主意。)

另一个例子:特定的命令会接受许多在多次运行中都不发生变化的选项;例如,bdist_rpm 需要知道为创建 RPM 发布包生成 "spec" 文件所要求的所有信息。 这些信息有的来自安装脚本,有的由 Distutils 自动生成(例如已安装文件列表)。 但有的则必须作为 bdist_rpm 的选项提供,每次运行时都在命令行中完成将会非常繁琐。 因此,这里提供 Distutils 本身的 setup.cfg 中的一段代码:

[bdist_rpm]
release = 1
packager = Greg Ward <gward@python.net>
doc_files = CHANGES.txt
            README.txt
            USAGE.txt
            doc/
            examples/

请注意 doc_files 选项只是一个空格分隔以提高可读性的多行字符串。

参见

"安装 Python 模块" 中的 Syntax of config files

有关配置文件的更多信息可在系统管理员手册中查看。

备注

1

在 Distutils 完全支持自动配置之前,这一理想可能是无法实现的。