2016-01-31 42 views
6

Mam projekt, który kompiluje się z rozszerzeniami C w systemie Linux, ale bez ich w systemie Windows. Kiedy po raz pierwszy wygenerowałem pliki kół w systemie Windows pod numerem python setup.py bdist_wheel, stały się one uniwersalne i nie mogłem ich przesłać do PyPI, ponieważ te uniwersalne kółka są preferowane przez pip do instalacji w stosunku do przesłanych .tar.gz (wynik z python setup.py sdist).'pip setup.py bdist_wheel' nie buduje już wymuszonych nieczystych kółek

Sztuką wokół to było określić w setup.py:

Distribution.is_pure = lambda *args: False 

lub przez instacji Distribution:

class BinaryDistribution(Distribution): 
    def is_pure(self): 
     return False 

i nazywając setup() w setup.py z dodatkowym kluczowego argumentu distclass=BinaryDistribution,.

Wszystko to działało dobrze na mojej maszynie wirtualnej z systemem Windows XP 64, która ma 32- i 64-bitowe wersje Pythona 2.6/2.7/3.3/3.4 i pypy zainstalowaną tylko w tym celu. Prosty plik wsadowy daje mi:

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 

i odpowiedni pakiet dostaje pobr i zainstalowane przez pip po uruchomieniu pip na Windows i po uruchomieniu pip na Linuksie masz

pkg-1.0.tar.gz 

który obejmuje Źródła C, które są kompilowane podczas instalacji.

Problem zaczął się od tego, że nie mam zapasowej maszyny z licencją Windows 7, w której mogę zainstalować Python 3.5 (nie instaluje się w EOL XP). Tak badałem Appveyor i stworzył 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\* 

Z dokładnie tego samego źródła wynik z powyższych ośmiu połączeń do python setup.py bdist_wheel są:

pkg-1.0-py2-none-any.whl 
pkg-1.0-py3-none-any.whl 

A jeśli przesłać je do PyPI, Linux preferuje je .tar.gz prowadzące do niewłączenia kodu rozszerzenia C.

Co jest tego przyczyną i jak mogę użyć Appveyor budować moje .whl plików (lub przynajmniej te, dla Pythona 3.5?

+0

I encoutered dokładnie ten sam problem, tylko teraz z Windows 7 i Python 3.5. Przywrócenie koła 0,24.0 rzeczywiście rozwiązuje problem. Próbowałem szukać, gdy koło 0.25+ zostało wydane, ale nie mogę znaleźć tagu na repo bitbucket. Dowolny pomysł ? – Overdrivr

+0

@Overdrivr To był 2015-09-17. takie informacje można łatwo znaleźć, patrząc na koło na [pypi] (https://pypi.python.org/pypi/wheel/0.25.0) (wyszukiwanie na samym pypi pokaże ci kilka starszych wersji lub zmień koniec sam adres URL 0.26.0) – Anthon

+0

@Overdrivr spójrz na moją zaktualizowaną odpowiedź, z 0.28 i opcją '--plat-name' możesz teraz nawet wygenerować pliki' .whl' na maszynie Linux, jeśli są czyste. – Anthon

Odpowiedz

2

Różnica jest oczywiście w środowisku, na prawidłowo pracuje Win XP jest zainstalowana starsza wersja pakietu wheel (0.24.0), podczas gdy na Appveyorze zainstalowana jest najnowsza i najlepsza (i uszkodzona) wersja koła 0,26 (również uszkodzone 0,25)

Zmiana sekcji instalacji w Plik YAML do naprawy wersji koła:

install: 
    - | 
    %PYTHON%\python.exe -m pip install --upgrade pip 
    %PYTHON%\python.exe -m pip install wheel==0.24 

wystarczy, aby to działało szybko.

Powinieneś jednak zaktualizować pakiet wheel na swoim Linux-Boksie do wersji 0.28, a następnie użyć nowej opcji poleceń --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 

które będą generować:

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 

które można przesyłać do PyPI i wyniki w pliku prawidłowego (.tar.gz) pobierania Linux i odpowiednie koło w systemie Windows. Robiąc tylko pewność, że jeśli podanosetup() jest wywoływana z ext_modules=None. Wynikowe pliki kół mają niewielkie (zakończenia linii w 3 plikach i ich SHA256SUM), ale instalują się normalnie w systemie Windows.

W ten sposób nie trzeba już budować te pakiety, które są zasadniczo czyste opakowania, na komputerze z systemem Windows

Dla mnie ta zmiana przez Nate Coraor przynosi mój całkowity czas budowy w dół od ponad 15 minut do około 7 sekund

11

właśnie napotkasz ten problem mnie z Python v2.7 i v0.29.0 koło na Windows 7 x64, gdzie zbudować pakiet Python z niektórych prekompilowanymi rozszerzeń (skomplikowane konfiguracji VisualStudio z SWIG i zewnętrznymi bibliotekami DLL).

Po zbadaniu kodu źródłowego I odkryli, że nadrzędnymi Distribution.has_ext_modules prace (automatycznie i zawiera nazwę platformy tag 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)