[英]Distribute pre-compiled python extension module with distutils
今天快速介绍一下:我正在学习 Python 的 distutils 库的来龙去脉,我想在我的包中包含一个 python 扩展模块 (.pyd)。 我当然知道推荐的方法是在创建包时让 distutils 编译扩展,但这是一个相当复杂的扩展,跨越许多源文件并引用多个外部库,因此需要一些重要的操作才能获得所有内容工作正常。
与此同时,我有一个来自 Visual Studio 的已知扩展工作版本,并希望在安装程序中使用它作为临时解决方案,以便我可以专注于其他问题。 但是,我无法将其指定为模块,因为那些显然必须具有显式的 .py 扩展名。 我怎么能在我的 setup.py 中表明我想要包含一个预编译的扩展模块?
(Python 3.1,如果重要的话)
我通过重写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)
在使用Python 3.7,CMake 3.15.3和Swig 4.0.1和Visual Studio 2017构建扩展库时,我遇到了同样的问题。构建系统生成三个文件:mymodule.py,_mymodule.lib和_mymodule.pyd。 经过一堆反复的试验,我发现以下组合可以工作:
[metadata]
name = mymodule
version = 1.0
[options]
include_package_data = True
package_dir=
=src
packages=mymodule
python_requires '>=3.7'
[options.package_data]
* = *.pyd
setup.py
setup.cfg
src/
mymodule/
__init__.py
_mymodule.pyd
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软件包,而不是尝试使用默认的build输出作为Python脚本进行安装。
我遇到过同样的问题。 这就是对我有用的方法。 我已经更改了模块的名称,只是为了一个简单的例子。
我的设置是: Visual Studio 2017 项目,它使用最终文件名 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 .
我得到了一个非常漂亮的轮子,其中包含扩展以及所需的存根。
尝试使用package_data: http : //docs.python.org/distutils/setupscript#installing-package-data
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.