假设我有一个结构如下的 python 包:
foo/
__init__.py
setup.py
bar/
__init__.py
bar.pyx
而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()]
)
然后我就跑
python setup.py build_ext --inplace
因为我需要编译后的文件bar.so正好放在bar/中。但是前面的命令在 bar 下创建了一个新目录 foo/bar/,并将 bar.so 放在那里,比如说,
foo/
__init__.py
setup.py
bar/
__init__.py
bar.pyx
foo/
bar/
bar.so
我需要的是
foo/
__init__.py
setup.py
bar/
__init__.py
bar.pyx
bar.so
这些烦人的事情发生在我把foo和bar打包之后。如果我删除 foo/__init__.py 和 bar/__init__.py 然后 bar.so 会出现在 foo/,仍然不是 foo/bar/。我已阅读手册,但没有找到解决此问题的选项。
那么如果我要求bar.so出现在正确的位置,同时保留两个__init__.py文件怎么办?
请您参考如下方法:
setup.py 不应位于包内。您需要将包向上移动一个目录:
foo/
setup.py
foo/
__init__.py
bar/
__init__.py
bar.pyx
这是我遇到的大多数包所遵循的结构。
至于 scikit-learn,您曾用它来获得灵感:
我当然不知道 scikit-learn 对它们的多个 setup.py 文件做了什么,但我敢打赌,并说外部 setup.py 正在使用(调用、导入)其他 setup.py,将子包配置的详细信息分发给那些单独的 setup.py。它只是不是很明显,因为(我认为)distutils/setuptools 在幕后做了很多这样的导入。
因此,外部设置负责整个包,内部设置负责子包的细节。
但到头来,它仍然是另一层的一个大setup.py文件。尝试运行
python setup.py build_ext --inplace
在任何内部 setup.py 上,它要么失败,要么什么都不做(至少对于我给它的两次尝试)。
因此,这些子包 setup.py 可能更恰本地被视为 setup_config.py 文件。
作为一个有趣的结果,安装包会将那些 setup.py 文件保留在它们各自的子包中(以及 sklearn 中的文件)。当人们使用这些包时,也许会有一些用处,但我想这只是 scikit-learn 设置过程和包含所有 *.py 文件的产物。
