命令 `python setup.py build_ext --inplace` 总是创建一个新目录

xyg*_*guo 2 python cython setup.py python-2.7

假设我有一个如下结构的 python 包:

foo/
  __init__.py
  setup.py
  bar/
    __init__.py
    bar.pyx
Run Code Online (Sandbox Code Playgroud)

的内容setup.py

from distutils.core import setup
from Cython.Build import cythonize
import numpy as np

setup(
    ext_modules=cythonize("bar/bar.pyx"),
    include_dirs=[np.get_include()]
)
Run Code Online (Sandbox Code Playgroud)

然后我就跑

python setup.py build_ext --inplace
Run Code Online (Sandbox Code Playgroud)

因为我需要将编译后的文件bar.so准确放置在bar/. 但是前面的命令foo/bar/在 下创建了一个新目录bar,并放在bar.so那里,比如说,

foo/
  __init__.py
  setup.py
  bar/
    __init__.py
    bar.pyx
    foo/
      bar/
        bar.so
Run Code Online (Sandbox Code Playgroud)

而我需要的是

foo/
  __init__.py
  setup.py
  bar/
    __init__.py
    bar.pyx
    bar.so
Run Code Online (Sandbox Code Playgroud)

这些烦人的事情发生在我转身foo成为bar一个包裹之后。如果我删除foo/__init__.py然后会出现在,仍然不会bar/__init__.py。我已阅读手册,但没有找到解决此问题的选项。bar.sofoo/foo/bar/

那么如果我要求bar.so出现在正确的位置,同时保留这两个__init__.py文件该怎么办呢?

小智 5

setup.py不应该生活在包裹内。您需要将包向上移动一个目录:

foo/
  setup.py
  foo/
    __init__.py
    bar/
      __init__.py
      bar.pyx
Run Code Online (Sandbox Code Playgroud)

这是我遇到的大多数包所遵循的结构。


至于 scikit-learn,您曾用它来获取灵感:

我当然不知道 scikit-learn 到底对它们的多个setup.py文件做了什么,但我敢打赌,并说外部setup.py正在使用(调用、导入)其他setup.py文件,来分发一个配置的详细信息分包到那些个体setup.pys。它只是不太明显,因为(我认为)distutils/setuptools 正在幕后进行大量的导入工作。

因此,外部设置负责整个包的处理,内部设置负责子包的具体细节。

但最终还是setup.py另一层的一个大文件。尝试跑步

python setup.py build_ext --inplace
Run Code Online (Sandbox Code Playgroud)

在任何内部setup.pys 上,它要么失败,要么什么也不做(至少对于我给出的两次尝试)。

因此,这些子包setup.py可能更适合被视为setup_config.py文件。

一个有趣的结果是,安装该包会将这些setup.py文件保留在各自的子包中(以及 中的子包sklearn)。也许当人们使用这些包时会有一些用处,但我想这只是 scikit-learn 设置过程和包含所有*.py文件的产物。