首页 > 解决方案 > setup.py 没有安装 swig 扩展模块

问题描述

我正在努力弄清楚如何将 swig 生成的包装器复制到与 swig 共享库相同的级别。考虑这个树结构:

│   .gitignore
│   setup.py
│
├───hello
├───src
│       hello.c
│       hello.h
│       hello.i
│
└───test
        test_hello.py

这个 setup.py:

import os
import sys

from setuptools import setup, find_packages, Extension
from setuptools.command.build_py import build_py as _build_py


class build_py(_build_py):
    def run(self):
        self.run_command("build_ext")
        return super().run()


setup(
    name='hello_world',
    version='0.1',
    cmdclass={'build_py': build_py},
    packages=["hello"],
    ext_modules=[
        Extension(
            'hello._hello',
            [
                'src/hello.i',
                'src/hello.c'
            ],
            include_dirs=[
                "src",
            ],
            depends=[
                'src/hello.h'
            ],
        )
    ],
    py_modules=[
        "hello"
    ],
)

当我这样做时,pip install .我将在站点包上获得此内容:

>tree /f d:\virtual_envs\py364_32\Lib\site-packages\hello                            
D:\VIRTUAL_ENVS\PY364_32\LIB\SITE-PACKAGES\HELLO                                                                 
    _hello.cp36-win32.pyd                                                                                        


>tree /f d:\virtual_envs\py364_32\Lib\site-packages\hello_world-0.1.dist-info        
D:\VIRTUAL_ENVS\PY364_32\LIB\SITE-PACKAGES\HELLO_WORLD-0.1.DIST-INFO                                             
    INSTALLER                                                                                                    
    METADATA                                                                                                     
    RECORD                                                                                                       
    top_level.txt                                                                                                
    WHEEL  

如您所见hello.py(由 swig 生成的文件)尚未复制到site-packages.

问题是,我已经尝试了以下类似帖子的许多答案:

不幸的是,这个问题仍然没有解决。

问题:如何修复我当前的 setup.py 以便将 swig 包装器复制到与 .pyd 文件相同的级别?

标签: pythonswigsetuptoolsdistutils

解决方案


setuptools不能按照您想要的方式执行此操作:它只会查找py_modules位于setup.py的位置。恕我直言,最简单的方法是将 SWIG 模块保留在命名空间/目录结构中您希望它们的位置:重命名srchello,然后添加hello/__init__.py(可能为空或仅包含来自 的所有内容hello.hello),留下这棵树:

$ tree .
.
├── hello
│   ├── __init__.py
│   ├── _hello.cpython-37m-darwin.so
│   ├── hello.c
│   ├── hello.h
│   ├── hello.i
│   ├── hello.py
│   └── hello_wrap.c
└── setup.py

py_modules从中删除setup.py"hello"列表中的将package提取setuptools整个包,并包含__init__.py和生成的hello.py

import os
import sys

from setuptools import setup, find_packages, Extension
from setuptools.command.build_py import build_py as _build_py


class build_py(_build_py):
    def run(self):
        self.run_command("build_ext")
        return super().run()


setup(
    name='hello_world',
    version='0.1',
    cmdclass={'build_py': build_py},
    packages = ["hello"],
    ext_modules=[
        Extension(
            'hello._hello',
            [
                'hello/hello.i',
                'hello/hello.c'
            ],
            include_dirs=[
                "hello",
            ],
            depends=[
                'hello/hello.h'
            ],
        )
    ],
)

这样,包也可以.egg-link工作(python setup.py develop),因此您可以将正在开发的包链接到 venv 左右。这也是setuptools(和distutils)工作方式的原因:开发沙箱的结构应该允许直接从其中运行代码,而不需要移动模块。

然后,SWIG 生成hello.py的和生成的扩展_hello将存在于hello

>>> from hello import hello, _hello
>>> print(hello)
<module 'hello.hello' from '~/so56562132/hello/hello.py'>
>>> print(_hello)
<module 'hello._hello' from '~/so56562132/hello/_hello.cpython-37m-darwin.so'>

(从扩展文件名可以看出,我现在在 Mac 上,但在 Windows 下完全一样)

此外,除了打包之外,在 SWIG 手册中有更多关于 SWIG 和 Python 命名空间和包的有用信息:http: //swig.org/Doc4.0/Python.html#Python_nn72


推荐阅读