Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用setuptools和swig构建模块_Python_Python 3.x_Swig_Setuptools - Fatal编程技术网

Python 使用setuptools和swig构建模块

Python 使用setuptools和swig构建模块,python,python-3.x,swig,setuptools,Python,Python 3.x,Swig,Setuptools,我有很多SWIG接口(foo.I、bar.I等)。我想使用setuptools将它们构建到我的平台(MS Windows)的Python(3.6.4)模块中。该模块应包括SWIG生成的Python文件(*.py)、二进制扩展(*.pyd)和编译的缓存(*.pyc)。My setup.py本质上是这样的: from setuptools import setup, Extension from pathlib import Path paths=list(Path('.').glob('*.i')

我有很多SWIG接口(foo.I、bar.I等)。我想使用setuptools将它们构建到我的平台(MS Windows)的Python(3.6.4)模块中。该模块应包括SWIG生成的Python文件(*.py)、二进制扩展(*.pyd)和编译的缓存(*.pyc)。My setup.py本质上是这样的:

from setuptools import setup, Extension
from pathlib import Path
paths=list(Path('.').glob('*.i'))
py=[path.stem for path in paths]
ext=[Extension('_' + path.stem, [str(path)]) for path in paths]
setup(py_modules=py, ext_modules=ext)
ext=[Extension(name='_' + path.stem,
            sources=[str(path)],
            swig_opts=['-I../include', '-c++'],
            include_dirs=['../include'])
            for path in paths]
现在,我通过以下步骤构建它:

python setup.py build_ext -I..\include --swig-opts="-I..\include -c++" -b pkg
python setup.py build_py -c -d pkg
echo. > pkg\__init__.py
通过这些步骤,我在
pkg
目录下得到了我想要的东西

我的问题是:使用一次调用
setup.py
,例如
setup.py build
,是否无法获得这种效果?我认为构建应该调用build_ext,但是我看不到如何传递,例如swig opts选项

更新 通过SWIG选项已解决(h/t@hoefling)。解决方案如下所示:

from setuptools import setup, Extension
from pathlib import Path
paths=list(Path('.').glob('*.i'))
py=[path.stem for path in paths]
ext=[Extension('_' + path.stem, [str(path)]) for path in paths]
setup(py_modules=py, ext_modules=ext)
ext=[Extension(name='_' + path.stem,
            sources=[str(path)],
            swig_opts=['-I../include', '-c++'],
            include_dirs=['../include'])
            for path in paths]
然而,随着洋葱层的剥落,我现在可以看到下面的一层,即:
setup.py build
作为一个调用,希望首先运行
build\u py
,然后运行
build\u ext
。你能理解为什么这个失败吗?我没有Python源代码。我的模块中的Python脚本将由SWIG生成,但SWIG只有在
build\u ext
步骤中才能运行。因此,我以同样的问题结束,那就是如何在一次调用中构建模块

C:\some\path> python setup.py build
running build
running build_py
file foo.py (for module foo) not found
file foo.py (for module foo) not found
running build_ext
building '_foo' extension
swigging foo.i to foo_wrap.cpp
swig.exe -python -I../include -c++ -o foo_wrap.cpp foo.i
creating build
creating build\temp.win-amd64-3.6
creating build\temp.win-amd64-3.6\Release
cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -I../include /EHsc /Tpfoo_wrap.cpp /Fobuild\temp.win-amd64-3.6\Release\foo_wrap.obj foo_wrap.cpp
Creating build\wib.win-amd64-3.6
link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /EXPORT:PyInit__foo build\temp.win-amd64-3.6\Release\foo_wrap.obj /IMPLIB:build\temp.win-amd64-3.6\Release\_foo.cp36-win_amd64.lib
Creating library build\temp.win-amd64-3.6\Release\_foo.cp36-win_amd64.lib and object build\temp.win-amd64-3.6\Release\_foo.cp36-win_amd64.exp
Generating code
Finished generating code
完成后,foo.py存在于foo.i旁边的当前工作目录中,而_foo.cp36-win_amd64.pyd存在于build\lib.win-amd64-3.6下。(仅供参考,为了保护专有信息,我对该成绩单进行了轻微编辑,例如,我没有显示所有命令回音的完整路径。我也没有在源代码中包含bar.I。)

澄清:

  • 错误是这样的:
    找不到文件foo.py(用于模块foo)

  • 虽然所有必需的文件都存在于输出中,但除了foo.cp36-win_amd64.pyc(我可能没有它),我必须手动将foo.py和_foo.cp36-win_amd64.pyd复制到某个新目录中,以创建一个干净的Python模块


  • 问题是,一旦您声明
    py_模块
    distutils
    build
    中包含
    build_py
    子命令,并且由于
    build
    类中的
    sub_命令
    列表的顺序,它总是首先执行。它根本不知道SWIG稍后将在
    build\u ext
    中生成python模块包装器。我想你可以把这看作是一个bug,因为人们期望
    distutils
    能够处理生成的模块,但是meh

    由于您只有SWIG接口,并且所有python模块都是生成的包装器(因此在您的情况下,
    build\u ext
    不依赖于
    build\u py
    ),因此您可以更改
    build
    中子命令的顺序,以便首先执行
    build\u ext
    ,然后执行其余命令。这将确保在执行
    build\u py
    之前生成python模块

    基本上,您需要重写
    build
    命令类,并更改
    sub_命令
    列表中元素的顺序。在python中有很多方法可以对列表重新排序;下面是我的建议。为了对列表进行重新排序,我使用了列表条件分区配方:

    由于基本思想(参见@hoefling的答案)是对build命令进行子类化,以设置其sub_commands属性,因此这是有效的:

    from setuptools import setup, Extension
    from distutils.command.build import build
    
    class build_alt_order(build):
      def __init__(self, *args):
        super().__init__(*args)
        self.sub_commands = [('build_ext', build.has_ext_modules),
                             ('build_py', build.has_pure_modules)]
    
    setup(py_modules=['foo.py', ...],
          ext_modules=[Extension('_foo', swig_opts=...), ...],
          cmdclass={'build':build_alt_order})
    
    setup.py
    中集成了一个带有SWIG的演示项目。 它有两个扩展。 其中一个(C。)是C,另一个是C++,带有STL(STLLIGH.SPEP,CPP)。 生成的py文件丢失的问题也可以通过
    类BuildPy(build\u py)
    解决


    build\u ext
    支持开箱即用的SWIG,因此
    扩展名(名称、文件、SWIG\u opts=['-I../include','-c++'])
    应该可以正常生成。@hoefling这对于传递SWIG选项是正确的,谢谢。至于其他错误-您能发布完整的错误消息吗?只需将文本从终端复制并粘贴到您的问题中。啊,我现在知道问题是什么了。执行此操作,并解释如何执行此操作。或者,这里有一个稍微简单的版本,我发现它也更通用,因为它也适用于
    安装