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

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

The setup configuration file is a useful middle-ground between the setup script —which, ideally, would be opaque to installers [1]—and the command-line to the setup script, which is outside of your control and entirely up to the installer. In fact, setup.cfg (and any other Distutils configuration files present on the target system) are processed after the contents of the setup script, but before the command-line. This has several useful consequences:

  • 安装者可以通过编辑 setup.cfg 来覆盖你放在 setup.py 中的配置
  • 你可以为无法在 setup.py 中方便设置的选项提供非标准的默认值
  • 安装者可以使用 setup.py 的命令行选项来覆盖 setup.cfg 中的一切

The basic syntax of the configuration file is simple:

[command]
option=value
...

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

You can find out the list of options supported by a particular command with the universal --help option, e.g.

> 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

For example, say you want your extensions to be built 「in-place」—that is, you have an extension pkg.ext, and you want the compiled extension file (ext.so on Unix, say) to be put in the same source directory as your pure Python modules pkg.mod1 and pkg.mod2. You can always use the --inplace option on the command-line to ensure this:

python setup.py build_ext --inplace

But this requires that you always specify the build_ext command explicitly, and remember to provide --inplace. An easier way is to 「set and forget」 this option, by encoding it in setup.cfg, the configuration file for this distribution:

[build_ext]
inplace=1

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

Another example: certain commands take a lot of options that don’t change from run to run; for example, bdist_rpm needs to know everything required to generate a 「spec」 file for creating an RPM distribution. Some of this information comes from the setup script, and some is automatically generated by the Distutils (such as the list of files installed). But some of it has to be supplied as options to bdist_rpm, which would be very tedious to do on the command-line for every run. Hence, here is a snippet from the Distutils』 own 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 完全支持自动配置之前,这一理想可能是无法实现的。