4

我已经定义了一个自定义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 安装它之后,foo我的 virtualenv 的 site-packages 目录中有一个模块。目录结构如下所示。

foo/
foo/__init__.py
foo/_foo.so

egg-info/SOURCES.txt文件不包括__init__.py我手动创建/移动的文件。当我执行pip uninstall foo命令时,命令会留foo/__init__.py在我的 virtualenv 的站点包中。我想 pip 删除整个包。如何将__init__.py我手动移动到构建目录的生成文件添加到已安装的输出文件列表中?

我意识到这是令人作呕和骇人听闻的,所以我欢迎恶心和骇人听闻的答案!

尝试:

  1. 添加packages=['foo']-当我这样做时,pip 不会构建扩展。还尝试调整包名称的文件路径/命名空间版本——没有区别。
4

2 回答 2

5

为了让 distutils 安装 Python 包,您需要传递packages=['foo'],并且如果您将它放在不是项目根级别的地方(我的意思是 setup.py 脚本旁边的 foo 目录),就像您看起来的那样要做到这一点,你还必须通过package_dir={'foo': 'Source'}或使用更简单的布局。如果您的 setup.py 脚本包含此packages参数,则 build 命令将调用 build_py 命令将 Python 源文件(和目录)移动到 build 目录,稍后将由 install 命令复制该目录。

这里的问题是您的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})

The elements in the sub_commands attribute are tuples of (command name, function to call to decide whether to run the command or not); this is documented in the source code but I don’t remember if it’s explained in the doc. In the standard build class build_py precedes build_clib. I may change this in the next version of Python 2.7, as it was reported that it interacted badly with 2to3 conversion.

于 2012-05-16T04:34:19.347 回答
1

首先,您的 Extension 实例中的 name 参数应该是模块名称 (foo._foo),而不是路径。

您是否尝试将 packages=['foo'] 添加到您的设置调用中?

于 2012-05-12T03:56:24.783 回答