我有一个在Linux上编译C扩展的项目,但在Windows上没有。 当我第一次用python setup.py bdist_wheel
在Windows上生成轮子文件时,它们变得普遍了,我不能将它们上传到PyPI,因为这些通用轮子是由pip
首选的.tar.gz
上传( python setup.py sdist
的结果python setup.py sdist
)。
这个技巧是在setup.py
指定的:
Distribution.is_pure = lambda *args: False
或通过子类Distribution
:
class BinaryDistribution(Distribution): def is_pure(self): return False
并使用extra关键字参数distclass=BinaryDistribution,
调用setup.py中的setup()
。
这在运行Windows XP 64的虚拟机上运行得很好,它具有32位和64位版本的Python 2.6 / 2.7 / 3.3 / 3.4和pypy,仅用于此目的。 一个简单的batch file给我:
dist/pkg-1.0-cp26-none-win32.whl dist/pkg-1.0-cp26-none-win_amd64.whl dist/pkg-1.0-cp27-none-win32.whl dist/pkg-1.0-cp27-none-win_amd64.whl dist/pkg-1.0-cp33-none-win32.whl dist/pkg-1.0-cp33-none-win_amd64.whl dist/pkg-1.0-cp34-none-win32.whl dist/pkg-1.0-cp34-none-win_amd64.whl
当你在Windows上运行pip
在Linux上运行pip
时,相应的软件包会被下载并通过pip
安装,
pkg-1.0.tar.gz
其中包含安装期间编译的C源代码。
问题始于我没有备用的Windows 7许可机器,我可以安装Python 3.5(它不安装在EOL XP上)。 所以我调查了Appveyor并创build了appveyor.yml
:
environment: matrix: - PYTHON: C:\Python27 - PYTHON: C:\Python33 - PYTHON: C:\Python34 - PYTHON: C:\Python35 - PYTHON: C:\Python27-x64 - PYTHON: C:\Python33-x64 DISTUTILS_USE_SDK: '1' - PYTHON: 'C:\Python34-x64' DISTUTILS_USE_SDK: '1' - PYTHON: 'C:\Python35-x64' install: - | %PYTHON%\python.exe -m pip install --upgrade pip %PYTHON%\python.exe -m pip install wheel build: off test_script: - echo Skipped for now after_test: - | %PYTHON%\python.exe setup.py bdist_wheel artifacts: - path: dist\*
上面八个调用python setup.py bdist_wheel
是一样的:
pkg-1.0-py2-none-any.whl pkg-1.0-py3-none-any.whl
如果你将这些file upload到PyPI,那么Linux会比.tar.gz
更喜欢它们,导致不包含C扩展代码。
是什么原因造成的,我怎样才能使用Appveyor构build我的.whl
文件(或者至less是Python 3.5的文件?
我刚刚在Windows 7 x64上使用Python v2.7和wheel v0.29.0来处理这个问题,在那里我用一些预编译的扩展(带有SWIG和外部DLL的复杂VisualStudio设置)构建了一个Python包。
在检查源代码后,我发现覆盖Distribution.has_ext_modules
作品(自动包含平台名称和ABI标签):
from setuptools import setup from setuptools.dist import Distribution DISTNAME = "packagename" DESCRIPTION = "" MAINTAINER = "" MAINTAINER_EMAIL = "" URL = "" LICENSE = "" DOWNLOAD_URL = "" VERSION = '1.2' PYTHON_VERSION = (2, 7) # Tested with wheel v0.29.0 class BinaryDistribution(Distribution): """Distribution which always forces a binary package with platform name""" def has_ext_modules(foo): return True setup(name=DISTNAME, description=DESCRIPTION, maintainer=MAINTAINER, maintainer_email=MAINTAINER_EMAIL, url=URL, license=LICENSE, download_url=DOWNLOAD_URL, version=VERSION, packages=["packagename"], # Include pre-compiled extension package_data={"packagename": ["_precompiled_extension.pyd"]}, distclass=BinaryDistribution)
当然,差异是在环境中,正确工作的Win XP中安装了一个较旧版本的wheel
包(0.24.0),而在Appveyor上安装了wheel
的最新和最大(和破碎)的0.26版本0.25也被打破)。
更改YAML文件中的安装节以修复轮子版本:
install: - | %PYTHON%\python.exe -m pip install --upgrade pip %PYTHON%\python.exe -m pip install wheel==0.24
足以让这个快速工作。
但是,您应该将您的Linux机箱上的wheel包升级到0.28版,然后使用新的命令行选项--plat-name
:
python setup.py sdist python2 setup.py bdist_wheel --plat-name win32 python2 setup.py bdist_wheel --plat-name win_amd64 python3 setup.py bdist_wheel --plat-name win32 python3 setup.py bdist_wheel --plat-name win_amd64
这将产生:
pkg-1.1.tar.gz dist/pkg-1.1-py2-none-win32.whl dist/pkg-1.1-py2-none-win32.whl dist/pkg-1.1-py3-none-win_amd64.whl dist/pkg-1.1-py3-none-win32.whl dist/pkg-1.0-cp34-none-win_amd64.whl
您可以将其上载到PyPI,并在Linux上正确( .tar.gz
)文件下载,并在Windows上正确下载。 通过确保如果指定了--plat-name win...
,那么使用ext_modules=None
调用setup()
。 由此产生的wheel文件在3个文件和它们的SHA256SUM中都有次要的(行尾),但是在Windows上正常安装。
这样你就不再需要在Windows机器上构建这些基本上是纯软件包的软件包
对于我来说, Nate Coraor的这个改变将我的总体构建时间从15分钟缩短到了大约7 秒