我有一个在Linux上使用C扩展编译的项目,但没有
他们在Windows上。当我第一次使用python setup.py bdist_wheel
在Windows上生成轮盘文件时,它们变得通用,我无法将它们上传到PyPI,因为pip
首选这些万向轮用于安装
超过.tar.gz
次上传(python setup.py sdist
的结果)。
解决这个问题的方法是在setup.py
中指定:
Distribution.is_pure = lambda *args: False
或通过子类化Distribution
:
class BinaryDistribution(Distribution):
def is_pure(self):
return False
并使用额外的关键字参数setup()
在setup.py中调用distclass=BinaryDistribution,
。
这一切在我的运行Windows XP 64的VM上运行良好,其中包含32和64位版本的Python 2.6 / 2.7 / 3.3 / 3.4和pypy,仅用于此目的。一个简单的批处理文件给了我:
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并创建了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
如果您将这些内容上传到PyPI,Linux会优先于.tar.gz
,导致不包含C扩展代码。
是什么导致这种情况,我如何使用Appveyor构建我的.whl
文件(或者至少是Python 3.5的文件?
答案 0 :(得分:14)
我刚刚在Windows 7 x64上使用Python v2.7和wheel v0.29.0来解决这个问题,我在其中构建了一个带有一些预编译扩展的Python包(使用SWIG和外部DLL的复杂VisualStudio设置)。
检查源代码后,我发现覆盖map("world",proj="vandergrinten",fill=FALSE)
有效(自动包含平台名称和ABI标记):
Distribution.has_ext_modules
答案 1 :(得分:2)
当然,区别在于环境,正确运行的Win XP上安装了wheel
软件包的旧版本(0.24.0),而在Appveyor上安装了最新版本(并且已损坏)车轮安装版本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...
被指定setup()
,则使用ext_modules=None
进行调用。生成的轮文件有较小的(3个文件中的行结尾及其SHA256SUM),但在Windows上正常安装。
这样您就不再需要在Windows机器上构建这些基本上是纯软件包的软件包
对我来说, Nate Coraor 的这一变化使我的总构建时间从15分钟以上缩短到大约7 <强>秒
答案 2 :(得分:0)
替代方法似乎与接受的答案相同,但更为简洁的是:
from setuptools import setup
DISTNAME = "packagename"
DESCRIPTION = ""
MAINTAINER = ""
MAINTAINER_EMAIL = ""
URL = ""
LICENSE = ""
DOWNLOAD_URL = ""
VERSION = '1.2'
PYTHON_VERSION = (2, 7)
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"]},
has_ext_modules=lambda: True)