在distutils构建的C扩展中使用Sphinx

7 投票
2 回答
1047 浏览
提问于 2025-04-16 09:56

我写了一个Python模块,其中包含一个用C语言编写的子模块:这个模块叫做 foo,而C部分叫做 foo._bar。它的结构大致是这样的:

src/ 
  foo/__init__.py   <- contains the public stuff 
  foo/_bar/bar.c    <- the C extension
doc/                <- Sphinx configuration
  conf.py
  ...

foo/__init__.py 文件会导入 _bar,这样可以增强它的功能,而有用的内容则在 foo 模块中展示。当模块构建完成后,这一切都能正常工作,但显然在未编译的状态下是无法使用的,因为 _bar 在未构建时是不存在的。

我想用Sphinx来为这个项目做文档,并且希望在 foo 模块上使用 autodoc 扩展。这意味着我需要在生成文档之前先构建项目。

由于我使用distutils来构建,构建后的模块会放在一个名字不固定的目录 build/lib.linux-ARCH-PYVERSION 中——这就意味着我不能直接把这个目录写死在Sphinx的 conf.py 文件里。

那么,我该如何配置我的distutils setup.py 脚本,以便在构建好的模块上运行Sphinx构建器呢?

为了完整性,这里是对 setup 的调用('假'东西是自定义的构建器,它们是 buildbuild_ext 的子类):

setup(cmdclass = {
        'fake': fake,
        'build_ext_fake' : build_ext_fake
      },
      package_dir = {'': 'src'},
      packages = ['foo'],
      name = 'foo',
      version = '0.1',
      description = desc,
      ext_modules = [module_real])

2 个回答

2

有更简单的方法来获取构建目录的名字:

>>> from distutils.util import get_platform
>>> get_platform()
'linux-x86_64'

我就不多说了,你可以自己完成字符串的拼接 :)

解决你问题的另一种方法是,在你的 setup.py 文件旁边创建一个 setup.cfg 文件,内容如下:

[build_ext]
inplace = 1

这样做会把你的扩展模块放在它的父包目录下。Sphinx 应该能找到它。

5

既然distutils可以自动找到构建路径,那为什么不直接用它呢?

import distutils.command.build
from distutils.dist import Distribution

b = distutils.command.build.build(Distribution())
b.initialize_options()
b.finalize_options()

print b.build_temp

# If you're building a library, you might need:
print b.build_lib

# Other values of interest are:
b.build_purelib
b.build_platlib
b.build_scripts
b.build_base

虽然distutils的文档不多,但这里有一些简短的介绍,告诉你有哪些类型的构建。

撰写回答