2016-01-31 35 views
6

Ho un progetto che compila con estensioni C su Linux, ma senza su Windows. Quando ho generato per la prima volta i file wheel su Windows con python setup.py bdist_wheel, sono diventati universali e non è stato possibile caricarli su PyPI poiché queste ruote universali sono preferite da pip per l'installazione sui caricamenti .tar.gz (il risultato da python setup.py sdist).'pip setup.py bdist_wheel' non costruisce più ruote non pure forzate

Il trucco intorno a questo è stato quello di specificare nel setup.py:

Distribution.is_pure = lambda *args: False 

o sottoclasse Distribution:

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

e chiamando setup() in setup.py con l'argomento chiave in più distclass=BinaryDistribution,.

Questo ha funzionato perfettamente sulla mia macchina virtuale con Windows XP 64 che ha versioni a 32 e 64 bit di Python 2.6/2.7/3.3/3.4 e Pypy installato proprio per questo scopo. Un semplice file batch mi dà:

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 

e il pacchetto appropriato ottiene downloade e installato da pip quando si esegue pip su Windows e quando si esegue pip su Linux si ottiene il

pkg-1.0.tar.gz 

che comprende la C fonti che vengono compilate durante l'installazione.

Il problema è iniziato con il fatto che non dispongo di un computer con licenza Windows 7 di riserva in cui posso installare Python 3.5 (non viene installato su EOL XP). Così ho studiato Appveyor e creato 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\* 

Con la stessa fonte il risultato di quanto sopra otto chiamate al python setup.py bdist_wheel sono:

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

E se si carica questi per PyPI, Linux li preferisce over il .tar.gz che porta alla non inclusione del codice di estensione C.

cosa provoca questo, e come posso usare Appveyor per costruire i miei .whl file (o almeno quelli per Python 3.5?

+0

ho encoutered lo stesso identico problema solo ora, con Windows 7 e python 3.5. Tornando alle ruote 0.24.0 risolve davvero il problema. Ho provato a cercare quando sono stati rilasciati i dischi 0.25+ ma non riesci a trovare il tag sul repository di bitbucket. Qualche idea ? – Overdrivr

+0

@Overdrivr Questo era il 2015-09-17. tali informazioni possono essere facilmente trovate guardando la ruota su [pypi] (https://pypi.python.org/pypi/wheel/0.25.0) (la ricerca su pypi stesso ti mostrerà alcune versioni precedenti o cambierà la fine di l'URL da 0.26.0 stesso) – Anthon

+0

@Overdrivr guarda la mia risposta aggiornata, con 0.28 e l'opzione '--plat-name' ora puoi anche generare i file' .whl' su una macchina Linux se sono puri. – Anthon

risposta

2

La differenza, naturalmente, è l'ambiente, il lavoro correttamente Win XP c'è una versione precedente del pacchetto wheel installato (0.24.0) mentre su Appveyor viene installata la versione 0.26 della ruota più recente (e spezzata) (anche 0,25 è interrotta.)

Modifica della stanza di installazione nel File YAML per fissare la versione della ruota:

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

è sufficiente per farlo funzionare rapidamente.

Si dovrebbe tuttavia aggiornare il pacchetto ruota sulla propria macchina Linux alla versione 0.28 e quindi utilizzare la nuova opzione di comando --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 

che genererà:

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 

che puoi caricare sul PyPI ed i risultati nel file corretto (.tar.gz) scaricando su Linux e la ruota opportuna Su Windows. Facendo semplicemente sicuro che se lo --plat-name win... è specificato, setup() viene chiamato con ext_modules=None. I file delle ruote risultanti hanno minori (terminazioni di riga in 3 file e SHA256SUM), ma normalmente si installano su Windows.

In questo modo non è più necessario per costruire questi pacchetti, che sono essenzialmente pacchetti puri, su una macchina

di Windows Per me questo cambiamento Nate Coraor porta il mio tempo totale costruire giù da oltre 15 minuti a circa 7 secondi

11

Mi sono appena imbattuto in questo problema io stesso con Python v2.7 e ruota v0.29.0 su Windows 7 x64, dove costruisco un pacchetto Python con alcune estensioni precompilate (complicata installazione di VisualStudio con SWIG e DLL esterne).

Dopo aver esaminato il codice sorgente ho trovato che l'override Distribution.has_ext_modules opere (include automaticamente il nome della piattaforma e 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)