' pip setup.py bdist_wheel'不再制造强制非纯轮子

时间:2016-01-31 09:56:20

标签: python windows pypi python-wheel appveyor

我有一个在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的文件?

3 个答案:

答案 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)