我已经定义了一个自定义build_ext
来构建一个时髦的扩展程序,我正在努力使其对pip友好。以下是我正在做的修剪版本。
foo_ext = Extension(
name='foo/_foo',
sources=foo_sources,
)
class MyBuildExt(build_ext):
def build_extension(self, ext):
# This standalone script builds the __init__.py file
# and some .h files for the extension
check_call(['python', 'build_init_file.py'])
# Now that we've created all the init and .h code
# build the C/C++ extension using setuptools/distutils
build_ext.build_extension(self, ext)
# Include the generated __init__.py in the build directory
# which is something like `build/lib.linux-x86/foo/`.
# How can I get setuptools/distutils to install the
# generated file automatically?!
generated_file = 'Source/foo/__init__.py'
output_path = '/'.join(self.get_outputs()[0].split('/')[:-1])
self.move_file(generated_file, output_path)
setup(
...,
ext_modules = [foo_ext],
cmdclass={'build_ext' : MyBuildExt},
)
将这个模块打包并用pip安装后,我的virtualenv的site-packages目录中有一个模块foo
。目录结构如下所示。
foo/
foo/__init__.py
foo/_foo.so
egg-info/SOURCES.txt
文件不包含我手动创建/移动的__init__.py
文件。当我执行pip uninstall foo
时,命令会在我的virtualenv的site-packages中留下foo/__init__.py
。我想pip删除整个包。如何将手动移动到构建目录中的生成的__init__.py
文件添加到已安装的输出文件列表中?
我意识到这很令人作呕和hacky,所以我欢迎恶心和骇人听闻的答案!
packages=['foo']
- 当我这样做时,pip不会构建扩展程序。还尝试调整包名称的文件路径/命名空间版本 - 没有区别。答案 0 :(得分:4)
为了让distutils安装一个Python包,你需要传递packages=['foo']
,如果你把它放在一个不是项目根级别的地方(我的意思是设置旁边的foo目录) .py脚本),就像你似乎在这里做的那样,你还必须通过package_dir={'foo': 'Source'}
或使用更简单的布局。如果您的setup.py脚本包含此packages
参数,那么build命令将调用build_py命令将Python源文件(和目录)移动到构建目录,稍后将通过install命令复制该目录。 p>
这里的问题是你的foo/__init__.py
文件是由build_ext命令构建的,该命令在build_py之后运行。您需要使用自定义生成命令覆盖它:
class MyBuild(build):
sub_commands = [('build_clib', build.has_c_libraries),
('build_ext', build.has_ext_modules),
('build_py', build.has_pure_modules),
('build_scripts', build.has_scripts),
]
setup(..., cmdclass={'build': MyBuild, 'build_ext': MyBuildExt})
sub_commands属性中的元素是(命令名,调用函数以决定是否运行命令)的元组;这是在源代码中记录的,但我不记得它是否在文档中解释。在标准构建类中,build_py位于build_clib之前。我可能会在下一版本的Python 2.7中对此进行更改,因为据报道它与2to3转换的交互非常糟糕。
答案 1 :(得分:1)
首先,Extension实例中的name参数应该是模块名称(foo._foo),而不是路径。
您是否尝试过将packages = ['foo']添加到设置调用中?