19

Quick one today: I'm learning the in's and out's of Pythons distutils library, and I would like to include a python extension module (.pyd) with my package. I know of course that the recommended way is to have distutils compile the extension at the time the package is created, but this is a fairly complex extension spanning many source files and referencing several external libs so it's going to take some significant playing to get everything working right.

In the meantime I have a known working build of the extension coming out of Visual Studio, and would like to use it in the installer as a temporary solution to allow me to focus on other issues. I can't specify it as a module, however, since those apparently must have an explicit .py extension. How could I indicate in my setup.py that I want to include a pre-compiled extension module?

(Python 3.1, if it matters)

4

5 回答 5

9

尝试清单模板:

http://docs.python.org/distutils/sourcedist.html#specifying-the-files-to-distribute

于 2010-03-15T03:13:47.400 回答
8

我通过覆盖 Extension.build_extension 解决了这个问题:

setup_args = { ... }
if platform.system() == 'Windows':
    class my_build_ext(build_ext):
        def build_extension(self, ext):
            ''' Copies the already-compiled pyd
            '''
            import shutil
            import os.path
            try:
                os.makedirs(os.path.dirname(self.get_ext_fullpath(ext.name)))
            except WindowsError, e:
                if e.winerror != 183: # already exists
                    raise


            shutil.copyfile(os.path.join(this_dir, r'..\..\bin\Python%d%d\my.pyd' % sys.version_info[0:2]), self.get_ext_fullpath(ext.name))

    setup_args['cmdclass'] = {'build_ext': my_build_ext }

setup(**setup_args)
于 2012-08-17T19:33:55.387 回答
1

我在使用 Python 3.7、CMake 3.15.3 和 Swig 4.0.1 和 Visual Studio 2017 构建扩展库时遇到了同样的问题。构建系统生成三个文件:mymodule.py、_mymodule.lib 和 _mymodule.pyd。经过一堆试验和错误,我发现以下组合可以工作:

  1. 创建一个“setup.cfg”文件,指定您正在安装一个包;例如:
    [metadata]
    name = mymodule
    version = 1.0

    [options]
    include_package_data = True
    package_dir=
        =src
    packages=mymodule
    python_requires '>=3.7'

    [options.package_data]
    * = *.pyd
  1. 更改 CMake 以创建分发目录结构,如下所示:
    setup.py
    setup.cfg
    src/
        mymodule/
                 __init__.py
                 _mymodule.pyd
  1. 'setup.py' 文件就很简单了:
    setup()

这需要让 CMake 将“mymodule.py”输出文件重命名为“ init .py”。我使用 CMake 中的“安装”命令执行此操作:


    install (TARGETS ${SWIG_MODULE_${PROJECT_NAME}_REAL_NAME} DESTINATION "${CMAKE_BINARY_DIR}/dist/src/${PROJECT_NAME}")
    install (FILES 
            setup.py
            setup.cfg
            DESTINATION "${CMAKE_BINARY_DIR}/dist"
    )

    install (FILES
            ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.py
            DESTINATION "${CMAKE_BINARY_DIR}/dist/src/${PROJECT_NAME}"
            RENAME "__init__.py"

我相信进行这项工作的关键是将构建输出重组为 Python 包,而不是尝试让安装程序使用默认构建输出作为 Python 脚本。

于 2019-10-18T23:24:08.893 回答
0

尝试使用 package_data:http ://docs.python.org/distutils/setupscript#installing-package-data

于 2011-10-10T15:53:01.493 回答
0

我遇到过同样的问题。这对我来说已经解决了。我已经更改了模块的名称,只是为了一个简单的例子。

我的设置是: Visual Studio 2017 Project,它使用最终文件名 myextension.pyd 构建扩展

然后,我使用 mypy 模块中的 stubgen 在本地创建了该模块的存根。

这是我的文件树

myextension/__init__.pyi
myextension/submodule.pyi
setup.py
myextension.pyd

这是内容setup.py

from setuptools import setup, Distribution


class BinaryDistribution(Distribution):
    def has_ext_modules(foo):
        return True


setup(
    name='myextension',
    version='1.0.0',
    description='myextension Wrapper',
    packages=['', 'myextension'],
    package_data={
        'myextension': ['*.pyi'],
        '': ['myextension.pyd'],
    },
    distclass=BinaryDistribution
)

运行后,pip wheel .我得到了一个非常漂亮的轮子,其中包含扩展以及所需的存根。

于 2021-10-18T21:42:21.620 回答