打包 (numpy.distutils)#

警告

numpy.distutils 已被弃用,并且将在 Python >= 3.12 中移除.更多详情,请参见 numpy.distutils 的状态和迁移建议

警告

请注意,``setuptools`` 经常进行重大发布,这些发布可能包含破坏 numpy.distutils 的更改,这些更改将不再为新的 setuptools 版本更新.因此,建议在您的构建配置中为已知与您的构建兼容的 setuptools 的最后一个版本设置一个上限版本.

NumPy 提供了增强的 distutils 功能,使其更容易构建和安装子包、自动生成代码,以及使用 Fortran 编译库的扩展模块.在 numpy.distutils.misc_util 中也提供了一个有用的 Configuration 类,可以更容易地构造传递给 setup 函数的键值对(通过传递从类的 todict() 方法获得的字典).更多信息可在 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)[源代码][源代码]#

为给定的包名构造一个配置实例.如果 parent_name 不是 None,则将该包构造为 parent_name 包的子包.如果 top_pathpackage_path 是 None,则它们被假定为创建此实例的文件的路径.numpy 分发中的 setup.py 文件是使用 Configuration 实例的好例子.

todict()[源代码][源代码]#

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

示例

>>> setup(**config.todict())                           
get_distribution()[源代码][源代码]#

返回 self 的 distutils 分发对象.

get_subpackage(subpackage_name, subpackage_path=None, parent_name=None, caller_level=1)[源代码][源代码]#

返回子包配置列表.

参数:
subpackage_namestr 或 None

获取配置的子包名称.子包名称中的 ‘*’ 作为通配符处理.

subpackage_pathstr

如果为 None,则假定路径为本地路径加上子包名称.如果在子包路径中找不到 setup.py 文件,则使用默认配置.

parent_namestr

父名称.

add_subpackage(subpackage_name, subpackage_path=None, standalone=False)[源代码][源代码]#

将一个子包添加到当前配置实例.

这在为一个包添加子包的setup.py脚本中非常有用.

参数:
subpackage_namestr

子包的名称

subpackage_pathstr

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

standalonebool
add_data_files(*files)[源代码][源代码]#

将数据文件添加到配置数据 data_files.

参数:
filessequence

参数可以是

  • 2-序列 (<数据目录前缀>,<数据文件路径>)

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

备注

files 序列中每个元素的形式非常灵活,允许许多从包中获取文件并最终安装到系统中的组合.最基本的用法是 files 参数序列的元素为一个简单的文件名.这将导致从本地路径安装该文件到 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

其中 <package install directory> 是包(或子包)目录,例如 ‘/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)[源代码][源代码]#

递归地将 data_path 下的文件添加到 data_files 列表中.

递归地将 data_path 下的文件添加到要安装(和分发)的 data_files 列表中.data_path 可以是相对路径名、绝对路径名,或者是包含两个元素的元组,其中第一个元素表示数据目录应安装到安装目录中的位置.

参数:
data_pathseq 或 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)[源代码][源代码]#

添加路径到配置包含目录.

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

add_headers(*files)[源代码][源代码]#

将可安装的头文件添加到配置中.

将给定的文件序列添加到头文件列表的开头.默认情况下,头文件将安装在 <python-include>/<self.name.replace(‘.’,’/’)>/ 目录下.如果文件项是一个元组,那么它的第一个参数指定实际安装位置相对于 <python-include> 路径.

参数:
filesstr 或 seq

参数可以是以下之一:

  • 2-序列 (<includedir 后缀>,<头文件路径>)

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

add_extension(name, sources, **kw)[源代码][源代码]#

添加扩展到配置.

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

参数:
namestr

扩展的名称

sourcesseq

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

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字典或列表

要附加到关键词的 dict 或 dict 列表.

备注

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

add_library(name, sources, **build_info)[源代码][源代码]#

将库添加到配置中.

参数:
namestr

扩展的名称.

sourcessequence

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

build_info字典, 可选

以下键是允许的:

  • 取决于

  • include_dirs

  • extra_compiler_args

  • extra_f77_compile_args

  • extra_f90_compile_args

  • f2py_options

  • language

add_scripts(*files)[源代码][源代码]#

将脚本添加到配置中.

将文件序列添加到脚本列表的开头.脚本将被安装在 <prefix>/bin/ 目录下.

add_installed_library(name, sources, install_dir, build_info=None)[源代码][源代码]#

类似于 add_library,但指定的库是已安装的.

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

参数:
namestr

已安装库的名称.

sourcessequence

库的源文件列表.详情请参见 add_library.

install_dirstr

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

build_info字典, 可选

以下键是允许的:

  • 取决于

  • include_dirs

  • extra_compiler_args

  • extra_f77_compile_args

  • extra_f90_compile_args

  • f2py_options

  • language

返回:
None

备注

编码链接指定C库所需选项的最佳方法是使用一个”libname.ini”文件,并使用 get_info 来检索所需的选项(更多信息请参见 add_npy_pkg_config).

add_npy_pkg_config(template, install_dir, subst_dict=None)[源代码][源代码]#

从模板生成并安装一个 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)[源代码][源代码]#

如果需要,对路径应用 glob 并在前面加上 local_path.

对序列中的每个路径(如果需要)应用 glob.glob(…) 并在需要时在前面加上 local_path.因为这会在所有源列表上调用,这允许在扩展模块、库和脚本的源列表中指定通配符字符,并允许路径名相对于源目录.

get_config_cmd()[源代码][源代码]#

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

get_build_temp_dir()[源代码][源代码]#

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

have_f77c()[源代码][源代码]#

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

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

备注

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

have_f90c()[源代码][源代码]#

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

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

备注

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

get_version(version_file=None, version_variable=None)[源代码][源代码]#

尝试获取一个包的版本字符串.

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

备注

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

make_svn_version_py(delete=True)[源代码][源代码]#

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

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

备注

如果 __svn_version__.py 之前存在,则什么也不做.

这是用于处理位于 SVN 仓库中的源目录.

make_config_py(name='__config__')[源代码][源代码]#

生成包含系统信息信息的包 __config__.py 文件,该信息在构建包期间使用.

此文件安装到包安装目录.

get_info(*names)[源代码][源代码]#

获取资源信息.

返回一个字典中所有参数列表中名称的信息(来自 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 支持自动转换名为 <somefile>.src 的源文件.这个功能可以用来维护非常相似的代码块,这些代码块之间只需要简单的更改.在 setup 的构建阶段,如果遇到名为 <somefile>.src 的模板文件,则会从模板构建一个名为 <somefile> 的新文件,并将其放置在构建目录中以供使用.支持两种形式的模板转换.第一种形式适用于名为 <file>.ext.src 的文件,其中 ext 是可识别的 Fortran 扩展(f, f90, f95, f77, for, ftn, pyf).第二种形式用于所有其他情况.请参见 使用模板转换 .src 文件.