打包#

警告

numpy.distutils 已被弃用,并将在 Python >= 3.12 中移除。有关更多详细信息,请参阅 numpy.distutils 的状态和迁移建议

警告

请注意,setuptools 经常发布主要版本,这些版本可能包含导致 numpy.distutils 损坏的更改,而 numpy.distutils不再针对新的 setuptools 版本进行更新。因此,建议在您的构建配置中为已知能与您的构建兼容的最后一个 setuptools 版本设置一个上限。

NumPy 提供了增强的 distutils 功能,以便更容易地构建和安装子包、自动生成代码以及使用 Fortran 编译库的扩展模块。在 numpy.distutils.misc_util 中还提供了一个有用的 Configuration 类,通过传递从该类的 todict() 方法获得的字典,可以更轻松地构造传递给 setup 函数的关键字参数。更多信息可在 numpy.distutils 用户指南 中找到。

链接库(如 BLAS 和 LAPACK)的选择和位置、包含路径以及其他此类构建选项可以在 NumPy 根存储库中的 site.cfg 文件或您主目录中的 .numpy-site.cfg 文件中指定。有关文档,请参阅 NumPy 存储库或 sdist 中包含的 site.cfg.example 示例文件。

模块在 numpy.distutils#

ccompiler

ccompiler_opt

提供了 CCompilerOpt 类,用于处理 CPU/硬件优化,从解析命令参数开始,到管理 CPU 基线和可分派功能之间的关系,还生成所需的 C 头文件,并最终使用适当的编译器标志编译源代码。

cpuinfo.cpu

core.Extension(name, sources[, ...])

参数:

exec_command

exec_command

log.set_verbosity(v[, force])

system_info.get_info(name[, notfound_action])

notfound_action

system_info.get_standard_file(fname)

返回一个名为“fname”的文件列表,来源包括:1) 系统范围目录(此模块的目录位置)2) 用户 HOME 目录 (os.environ['HOME']) 3) 本地目录

配置类#

class numpy.distutils.misc_util.Configuration(package_name=None, parent_name=None, top_path=None, package_path=None, **attrs)[source]#

为给定的包名构造一个配置实例。如果 parent_name 不为 None,则将该包构造为 parent_name 包的子包。如果 top_pathpackage_path 均为 None,则假定它们等于创建此实例的文件路径。NumPy 发布版中的 setup.py 文件是使用 Configuration 实例的良好示例。

todict()[source]#

返回一个与 distutils setup 函数的关键字参数兼容的字典。

示例

>>> setup(**config.todict())                           
get_distribution()[source]#

返回自身的 distutils 分发对象。

get_subpackage(subpackage_name, subpackage_path=None, parent_name=None, caller_level=1)[source]#

返回子包配置列表。

参数:
subpackage_namestr 或 None

要获取配置的子包名称。subpackage_name 中的“*”被视为通配符。

subpackage_pathstr

如果为 None,则路径被假定为本地路径加上 subpackage_name。如果在 subpackage_path 中未找到 setup.py 文件,则使用默认配置。

parent_namestr

父名称。

add_subpackage(subpackage_name, subpackage_path=None, standalone=False)[source]#

向当前 Configuration 实例添加一个子包。

这在 setup.py 脚本中添加子包到包时非常有用。

参数:
subpackage_namestr

子包的名称

subpackage_pathstr

如果给定,子包路径如子包在 subpackage_path / subpackage_name 中。如果为 None,则假定子包位于本地路径 / subpackage_name 中。

standalonebool
add_data_files(*files)[source]#

将数据文件添加到配置的 data_files 中。

参数:
filessequence

参数可以是以下形式:

  • 2 元组(,<数据文件路径>)

  • 数据文件路径,其中 python datadir 前缀默认为包目录。

注意

文件序列中每个元素的格式非常灵活,允许多种组合,以指定从包中获取文件和最终将文件安装到系统上的位置。最基本的使用方式是文件参数序列中的一个元素是一个简单的文件名。这将导致该文件从本地路径安装到 self.name 包的安装路径(包路径)。文件参数也可以是相对路径,在这种情况下,整个相对路径将被安装到包目录中。最后,文件可以是绝对路径名,在这种情况下,文件将在绝对路径名处找到,但仍安装到包路径。

可以通过将一个 2 元组作为文件参数来增强此基本行为。元组的第一个元素应指定剩余文件序列应安装到的相对路径(在包安装目录下)(它与源代码分发中的文件名无关)。元组的第二个元素是要安装的文件序列。此序列中的文件可以是文件名、相对路径或绝对路径。对于绝对路径,文件将安装在顶层包安装目录中(无论第一个参数是什么)。文件名和相对路径名将安装在包安装目录下,路径名由元组的第一个元素给出。

安装路径规则

  1. file.txt -> (., file.txt)-> parent/file.txt

  2. foo/file.txt -> (foo, foo/file.txt) -> parent/foo/file.txt

  3. /foo/bar/file.txt -> (., /foo/bar/file.txt) -> parent/file.txt

  4. *.txt -> parent/a.txt, parent/b.txt

  5. foo/*.txt`` -> parent/foo/a.txt, parent/foo/b.txt

  6. */*.txt -> (*, */*.txt) -> parent/c/a.txt, parent/d/b.txt

  7. (sun, file.txt) -> parent/sun/file.txt

  8. (sun, bar/file.txt) -> parent/sun/file.txt

  9. (sun, /foo/bar/file.txt) -> parent/sun/file.txt

  10. (sun, *.txt) -> parent/sun/a.txt, parent/sun/b.txt

  11. (sun, bar/*.txt) -> parent/sun/a.txt, parent/sun/b.txt

  12. (sun/*, */*.txt) -> parent/sun/c/a.txt, parent/d/b.txt

另一个特性是,数据文件路径实际上可以是一个不接受任何参数并返回数据文件实际路径的函数。当在构建包时生成数据文件时,这非常有用。

示例

将文件添加到要包含在包中的 data_files 列表。

>>> self.add_data_files('foo.dat',
...     ('fun', ['gun.dat', 'nun/pun.dat', '/tmp/sun.dat']),
...     'bar/cat.dat',
...     '/full/path/to/can.dat')                   

将这些数据文件安装到

<package install directory>/
 foo.dat
 fun/
   gun.dat
   nun/
     pun.dat
 sun.dat
 bar/
   car.dat
 can.dat

其中 <包安装目录> 是包(或子包)目录,例如 '/usr/lib/python2.4/site-packages/mypackage'('C: Python2.4 Lib site-packages mypackage')或 '/usr/lib/python2.4/site-packages/mypackage/mysubpackage'('C: Python2.4 Lib site-packages mypackage mysubpackage')。

add_data_dir(data_path)[source]#

将 data_path 下的文件递归添加到 data_files 列表。

将 data_path 下的文件递归添加到要安装(和分发)的 data_files 列表。data_path 可以是相对路径名、绝对路径名,也可以是 2 元组,其中第一个参数表示数据目录应安装到安装目录中的哪个位置。

参数:
data_path序列或 str

参数可以是以下形式:

  • 2 元组(, <数据目录路径>)

  • 数据目录路径,其中 python datadir 后缀默认为包目录。

注意

安装路径规则

foo/bar -> (foo/bar, foo/bar) -> parent/foo/bar
(gun, foo/bar) -> parent/gun
foo/* -> (foo/a, foo/a), (foo/b, foo/b) -> parent/foo/a, parent/foo/b
(gun, foo/*) -> (gun, foo/a), (gun, foo/b) -> gun
(gun/*, foo/*) -> parent/gun/a, parent/gun/b
/foo/bar -> (bar, /foo/bar) -> parent/bar
(gun, /foo/bar) -> parent/gun
(fun/*/gun/*, sun/foo/bar) -> parent/fun/foo/gun/bar

示例

例如,假设源目录包含 fun/foo.dat 和 fun/bar/car.dat

>>> self.add_data_dir('fun')                       
>>> self.add_data_dir(('sun', 'fun'))              
>>> self.add_data_dir(('gun', '/full/path/to/fun'))

将数据文件安装到以下位置

<package install directory>/
  fun/
    foo.dat
    bar/
      car.dat
  sun/
    foo.dat
    bar/
      car.dat
  gun/
    foo.dat
    car.dat
add_include_dirs(*paths)[source]#

将路径添加到配置的包含目录。

将给定的路径序列添加到 include_dirs 列表的开头。此列表将对当前包的所有扩展模块可见。

add_headers(*files)[source]#

将可安装头文件添加到配置。

将给定的文件序列添加到 headers 列表的开头。默认情况下,头文件将安装在 // 目录下。如果 files 中的一个项是元组,则其第一个参数指定相对于 路径的实际安装位置。

参数:
filesstr 或序列

参数可以是以下形式:

  • 2 元组(,<头文件路径>)

  • 头文件路径,其中 python includedir 后缀默认为包名。

add_extension(name, sources, **kw)[source]#

将扩展添加到配置。

创建并添加一个 Extension 实例到 ext_modules 列表。此方法还接受以下可选关键字参数,这些参数将传递给 Extension 构造函数。

参数:
namestr

扩展的名称

sources序列

源文件列表。源文件列表可以包含函数(称为源生成器),这些函数必须以扩展实例和构建目录作为输入,并返回一个源文件或源文件列表,或 None。如果返回 None,则不生成任何源文件。如果在处理所有源生成器后,Extension 实例没有源文件,则不构建任何扩展模块。

include_dirs
define_macros
undef_macros
library_dirs
libraries
runtime_library_dirs
extra_objects
extra_compile_args
extra_link_args
extra_f77_compile_args
extra_f90_compile_args
export_symbols
swig_opts
depends

depends 列表包含扩展模块源文件所依赖的文件或目录路径。如果 depends 列表中的任何路径比扩展模块新,则该模块将被重建。

language
f2py_options
module_dirs
extra_info字典或列表

要附加到关键字的关键字字典或字典列表。

注意

self.paths(…) 方法应用于所有可能包含路径的列表。

add_library(name, sources, **build_info)[source]#

将库添加到配置。

参数:
namestr

扩展的名称。

sources序列

源文件列表。源文件列表可以包含函数(称为源生成器),这些函数必须以扩展实例和构建目录作为输入,并返回一个源文件或源文件列表,或 None。如果返回 None,则不生成任何源文件。如果在处理所有源生成器后,Extension 实例没有源文件,则不构建任何扩展模块。

build_info字典,可选

允许以下键

  • depends

  • macros

  • include_dirs

  • extra_compiler_args

  • extra_f77_compile_args

  • extra_f90_compile_args

  • f2py_options

  • language

add_scripts(*files)[source]#

将脚本添加到配置。

将文件序列添加到 scripts 列表的开头。脚本将安装在 /bin/ 目录下。

add_installed_library(name, sources, install_dir, build_info=None)[source]#

类似于 add_library,但指定的库将被安装。

大多数与 distutils 一起使用的 C 库仅用于构建 Python 扩展,但通过此方法构建的库将被安装,以便第三方包可以重用它们。

参数:
namestr

已安装库的名称。

sources序列

库的源文件列表。详见 add_library

install_dirstr

安装库的路径,相对于当前子包。

build_info字典,可选

允许以下键

  • depends

  • macros

  • include_dirs

  • extra_compiler_args

  • extra_f77_compile_args

  • extra_f90_compile_args

  • f2py_options

  • language

返回:

注意

编码链接指定 C 库所需选项的最佳方法是使用“libname.ini”文件,并使用 get_info 来检索所需选项(详见 add_npy_pkg_config)。

add_npy_pkg_config(template, install_dir, subst_dict=None)[source]#

从模板生成并安装 npy-pkg 配置文件。

template 生成的配置文件将安装到给定安装目录中,并使用 subst_dict 进行变量替换。

参数:
templatestr

模板路径,相对于当前包路径。

install_dirstr

npy-pkg 配置文件安装位置,相对于当前包路径。

subst_dict字典,可选

如果给定,模板文件中的任何 @key@ 形式的字符串在安装时都将被 subst_dict[key] 替换。安装前缀始终可以通过变量 @prefix@ 获得,因为安装前缀不容易从 setup.py 中可靠地获取。

注意

这适用于标准安装和原地构建,即 @prefix@ 对于原地构建指代源目录。

示例

config.add_npy_pkg_config('foo.ini.in', 'lib', {'foo': bar})

假设 foo.ini.in 文件内容如下

[meta]
Name=@foo@
Version=1.0
Description=dummy description

[default]
Cflags=-I@prefix@/include
Libs=

生成的文件将包含以下内容

[meta]
Name=bar
Version=1.0
Description=dummy description

[default]
Cflags=-Iprefix_dir/include
Libs=

并将作为 foo.ini 安装到“lib”子路径中。

当使用 numpy distutils 进行交叉编译时,可能需要使用修改过的 npy-pkg-config 文件。使用默认/生成的文件将与主机库(即 libnpymath.a)链接。对于交叉编译,您当然需要链接目标库,同时使用主机 Python 安装。

您可以复制 numpy/_core/lib/npy-pkg-config 目录,向 .ini 文件添加 pkgdir 值,并设置 NPY_PKG_CONFIG_PATH 环境变量以指向包含修改后的 npy-pkg-config 文件的目录。

为交叉编译修改后的 npymath.ini 示例

[meta]
Name=npymath
Description=Portable, core math library implementing C99 standard
Version=0.1

[variables]
pkgname=numpy._core
pkgdir=/build/arm-linux-gnueabi/sysroot/usr/lib/python3.7/site-packages/numpy/_core
prefix=${pkgdir}
libdir=${prefix}/lib
includedir=${prefix}/include

[default]
Libs=-L${libdir} -lnpymath
Cflags=-I${includedir}
Requires=mlib

[msvc]
Libs=/LIBPATH:${libdir} npymath.lib
Cflags=/INCLUDE:${includedir}
Requires=mlib
paths(*paths, **kws)[source]#

如果需要,对路径应用 glob 并预置 local_path。

(如果需要)将 glob.glob(…) 应用于序列中的每个路径,并在需要时预置 local_path。由于此方法在所有源列表上调用,因此允许在扩展模块、库和脚本的源列表中指定通配符,并允许路径名相对于源目录。

get_config_cmd()[source]#

返回 numpy.distutils 配置命令实例。

get_build_temp_dir()[source]#

返回一个临时目录的路径,临时文件应放置在该目录中。

have_f77c()[source]#

检查 Fortran 77 编译器的可用性。

在源生成函数内部使用它,以确保 setup 分发实例已初始化。

注意

如果 Fortran 77 编译器可用(因为简单的 Fortran 77 代码能够成功编译),则为 True。

have_f90c()[source]#

检查 Fortran 90 编译器的可用性。

在源生成函数内部使用它,以确保 setup 分发实例已初始化。

注意

如果 Fortran 90 编译器可用(因为简单的 Fortran 90 代码能够成功编译),则为 True。

get_version(version_file=None, version_variable=None)[source]#

尝试获取包的版本字符串。

返回当前包的版本字符串,如果无法检测到版本信息则返回 None。

注意

此方法扫描名为 __version__.py、_version.py、version.py 和 __svn_version__.py 的文件,查找字符串变量 version、__version__ 和 _version,直到找到版本号。

make_svn_version_py(delete=True)[source]#

向 data_files 列表追加一个数据函数,该函数将生成 __svn_version__.py 文件到当前包目录。

从 SVN 修订号生成包的 __svn_version__.py 文件,该文件在 Python 退出后将被删除,但在执行 sdist 等命令时将可用。

注意

如果 __svn_version__.py 之前已存在,则不执行任何操作。

这适用于处理 SVN 存储库中的源目录。

make_config_py(name='__config__')[source]#

生成包的 __config__.py 文件,其中包含构建包时使用的 system_info 信息。

此文件将安装到包的安装目录。

get_info(*names)[source]#

获取资源信息。

以单个字典的形式返回参数列表中所有名称的信息(来自 system_info.get_info)。

构建可安装的 C 库#

常规 C 库(通过 add_library 安装)不会被安装,它们仅在构建期间使用(它们是静态链接的)。可安装的 C 库是纯 C 库,不依赖于 Python C 运行时,并且已安装以便第三方包可以使用。要构建和安装 C 库,您只需使用 add_installed_library 方法而不是 add_library,后者接受相同的参数,但多了一个 install_dir 参数。

.. hidden in a comment so as to be included in refguide but not rendered documentation
  >>> import numpy.distutils.misc_util
  >>> config = np.distutils.misc_util.Configuration(None, '', '.')
  >>> with open('foo.c', 'w') as f: pass

>>> config.add_installed_library('foo', sources=['foo.c'], install_dir='lib')

npy-pkg-config 文件#

为了使必要的构建选项可供第三方使用,您可以使用 numpy.distutils 中实现的 npy-pkg-config 机制。该机制基于一个包含所有选项的 .ini 文件。一个 .ini 文件与 pkg-config unix 工具使用的 .pc 文件非常相似。

[meta]
Name: foo
Version: 1.0
Description: foo library

[variables]
prefix = /home/user/local
libdir = ${prefix}/lib
includedir = ${prefix}/include

[default]
cflags = -I${includedir}
libs = -L${libdir} -lfoo

通常,该文件需要在构建期间生成,因为它需要一些仅在构建时才可知的信息(例如前缀)。如果使用 Configuration 方法 add_npy_pkg_config,这在很大程度上是自动的。假设我们有一个模板文件 foo.ini.in 如下:

[meta]
Name: foo
Version: @version@
Description: foo library

[variables]
prefix = @prefix@
libdir = ${prefix}/lib
includedir = ${prefix}/include

[default]
cflags = -I${includedir}
libs = -L${libdir} -lfoo

以及 setup.py 中的以下代码

>>> config.add_installed_library('foo', sources=['foo.c'], install_dir='lib')
>>> subst = {'version': '1.0'}
>>> config.add_npy_pkg_config('foo.ini.in', 'lib', subst_dict=subst)

这会将文件 foo.ini 安装到目录 package_dir/lib 中,并且 foo.ini 文件将从 foo.ini.in 生成,其中每个 @version@ 将被 subst_dict['version'] 替换。该字典还自动添加了一个额外的前缀替换规则,其中包含安装前缀(因为这不容易从 setup.py 中获取)。

重用其他包的 C 库#

信息可以很容易地从 numpy.distutils.misc_util 中的 get_info 函数中检索。

>>> info = np.distutils.misc_util.get_info('npymath')
>>> config.add_extension('foo', sources=['foo.c'], extra_info=info)
<numpy.distutils.extension.Extension('foo') at 0x...>

可以向 get_info 提供一个额外的 .ini 文件搜索路径列表。

.src 文件的转换#

NumPy distutils 支持自动转换名为 .src 的源文件。此功能可用于维护非常相似的代码块,仅需要在块之间进行简单更改。在 setup 的构建阶段,如果遇到名为 .src 的模板文件,则会从该模板构造一个名为 的新文件,并将其放置在构建目录中以供使用。支持两种形式的模板转换。第一种形式用于名为 .ext.src 的文件,其中 ext 是已识别的 Fortran 扩展名(f, f90, f95, f77, for, ftn, pyf)。第二种形式用于所有其他情况。详见 使用模板转换 .src 文件