2015-07-13 2 views
18

Ich baue ein Python-Paket mit einer C-Bibliothek mit Ctypes. Ich möchte mein Paket portierbar machen (Windows, Mac und Linux).Wie vermeidet man, C-Bibliothek mit meinem Python-Paket zu erstellen?

Ich habe eine Strategie gefunden, build_ext mit pip zu verwenden, um die Bibliothek während der Installation meines Pakets zu erstellen. Je nach Plattform des Ziels wird libfoo.dll oder libfoo.dylib oder libfoo.so erstellt.

Das Problem damit ist, dass mein Benutzer CMake installiert benötigt.

Gibt es eine andere Strategie, um das Bauen während der Installation zu vermeiden? Muss ich gebaute Bibliotheken in meinem Paket bündeln?

Ich möchte meine Benutzer tun pip install mylib.

bearbeiten: danke Kommentar @Dawid, Ich versuche, ein python wheel mit dem Befehl python setup.py bdist_wheel ohne Erfolg.

Wie kann ich mein Python Wheel für verschiedene Plattformen mit der eingebetteten Bibliothek erstellen?

Edit 2: ich Python bin mit 3.4 und arbeitet an Mac OS X, aber ich habe den Zugriff auf Windows-Computer und Linux-Computer

+0

Ja, Sie müssen Rad-Pakete (binär kompiliert) für bestimmte Plattformen, 'pip install wheel' erstellen und dann für die erforderlichen Plattformen bauen – Dawid

+0

@Dawid danke, ich habe versucht, ein Python-Rad zu erstellen, aber ich denke, ich bin etwas fehlt –

+0

Ich denke, Sie müssen Informationen über diese Bibliothek in 'setup.py' enthalten, so dass es gebaut würde. Etwas auf https://docs.python.org/3.4/extending/building.html auf diese Weise führt 'python setup.py bdist_wheel' auf jeder Plattform ein whl-Paket für diese Plattform mit kompilierter Bibliothek aus. Dann werden Benutzer unter Linux das Paket für Linux, Windows für Windows und Mac für Mac installieren. Zumindest was ich tun würde, um ein Binärpaket für diese Systeme zu erstellen. – Dawid

Antwort

8

Sie sind sicherlich auf dem richtigen Weg nach meinen Recherchen ... Wie Daniel sagt, die einzige Option, die Sie haben, ist die Binärdateien selbst zu bauen und zu verteilen.

Im Allgemeinen ist der empfohlene Weg zum Installieren von Paketen gut in der packaging user guide abgedeckt. Ich werde den Rat dort nicht wiederholen, da Sie es offenbar schon gefunden haben. Der entscheidende Punkt darin ist jedoch, dass die Python-Community, speziell PyPA versucht, die Verwendung von platform wheels zu standardisieren, um binäre Erweiterungen zu verpacken. Leider gibt es an dieser Stelle einige Probleme:

  1. Sie können keine Distributionen für alle Linux-Varianten erstellen, aber Sie können Räder für eine kompatible Untergruppe erstellen. Details finden Sie unter https://www.python.org/dev/peps/pep-0513/.
  2. Die advice on building extensions ist etwas unvollständig, was das Fehlen einer vollständigen Lösung für Binärdistributionen widerspiegelt.
  3. Leute versuchen dann, ihre eigene Bibliothek zu bauen und sie als eine Datendatei zu verteilen, die setuptools verwirrt.

Ich denke, dass Sie diese letzte Frage treffen. A workaround soll die Distribution zwingen, ein Plattformrad durch Überschreiben von is_pure() zu erstellen, um immer False zurückzugeben. Sie können jedoch einfach Ihre ursprünglichen Build-Anweisungen beibehalten und bdist_wheel sollte damit umgehen.

Sobald Sie das Rad jedoch gebaut haben, müssen Sie es noch verteilen und vielleicht andere Binärpakete, die es verwendet oder verwendet.An diesem Punkt müssen Sie wahrscheinlich einen der recommended tools wie Conda oder einen PyPI-Proxy wie devpi verwenden, um Ihre Räder zu servieren.

EDIT: Zur Beantwortung der zusätzlichen Frage zu Cross-Kompilierung

Wie bedeckt here Python 2.6 und höher ermöglicht Querübersetzbarkeit für Windows 32/64-Bit-Builds. Es gibt keine formelle Unterstützung für andere Pakete auf anderen Plattformen und die Leute hatten limited success versucht, es zu tun. Es ist wirklich das Beste, nativ in jeder Ihrer Linux/Mac/Windows-Umgebungen zu bauen.

+2

"Sie können keine Linux-Räder auf PyPI hochladen" Warum nicht? – endolith

+0

Gemäß der [Python Packaging Authority] (https://python-packaging-user-guide.readthedocs.io/distributing/#platform-wheels): "Derzeit wird die Variation nicht mit der Wheel-Tag-Spezifikation (PEP 425) behandelt das kann über Linux Distributionen existieren. ". –

+0

Nicht mehr: Linux-Räder werden jetzt auf PyPI unterstützt. Die Antwort wurde entsprechend aktualisiert. –

0

Wenn Sie den Benutzer während der Installation nicht bauen wollen , Sie müssen ein vorgefertigtes Binärpaket bereitstellen, ich glaube nicht, dass eine andere Strategie möglich ist. Ich habe gute Dinge über py2exe gehört, aber ich benutze keine Windows IDK. Ich habe gute Erfahrungen mit miniconda gemacht, aber es erfordert ein wenig zusätzliche Arbeit zu build binary packages from pypi.

+0

danke, aber ich bevorzuge meine Benutzer cygwin/mingw32 oder cmake installieren und eine 'pip install mylib' statt ein Installationsprogramm dafür zu erstellen. Ich möchte nur weiter gehen und versuchen, die CMake-Installation zu vermeiden. –

1

Ich bevorzuge meinen Benutzer cygwin/mingw32 oder cmake installieren und eine pip install mylib [...] tun. Ich will nur weiter gehen und versuchen, vermeiden die CMake Installation.

Informationen zum Paketieren vorkompilierter Python-Module finden Sie in der vollständigen Antwort von @Peter Brittain.

Nun angenommen, dass der Benutzer tatsächlich einen C-Compiler installiert hat (ob cygwin, conda unter Windows, oder das System unter Linux), und alles, was Sie wollen, ist die CMake-Installation zu vermeiden, die keine Beziehung Python-Verpackung hat .

Die Frage ist dann, wie viel Funktionalität von CMake Sie verwenden, und ob das gleiche kann mit einfacher erreicht werden Alternativen zu verwalten, finden Sie Fragen (1), (2) usw.

Edit: Insbesondere Ich dachte etwas in der Art von SCons, die ein vollständiges Build-System bietet, aber in Python geschrieben, so dass es einfacher ist, in einer Python-freundlichen Umgebung als CMake zu installieren, siehe full comparison here. Eine wilde Vermutung (ich habe es nie selbst benutzt), aber da es ein reines Python-Modul ist, könnten Sie wahrscheinlich SCons als eine Abhängigkeit in Ihrem setup.py setzen und den Build Ihres C-Codes dort vollständig automatisieren, so dass pip install mylib alles erledigt erforderlich. Siehe auch CMake2SCons Paket, das nützlich sein könnte.

+1

Momentan habe ich viele Pakete gesehen, die Extension() hacken, um ihre Bedürfnisse zu erfüllen, Compiler zu erkennen und Compilerparameter zu modifizieren. Cmake bewältigt diese Komplexität für mich. Ich habe einige libs (.dll und .dylib) erstellt, die auf verschiedenen Plattformen arbeiten. Ich versuche eine einfach zu implementierende Lösung zu finden, die aber auch einfach von meinem Benutzer installiert werden kann. –

3

@rth und @PeterBrittain hilf mir sehr. Hier ist die Lösung, die ich verwenden:

Struktur Ordner:

setup.py 
python_package/ 
    lib/ 
     libfoo.dylib 
     libfoo.dll 
    __init__.py 
    main.py 

setup.py:

from setuptools import setup, dist 


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


setup(
    name='python_package', 
    package_data={'python_package': ['lib/libfoo.dylib','lib/libfoo.dll']}, 
    include_package_data=True, 
    distclass=BinaryDistribution, 
    packages=['python_package'], 
) 

main.py:

#!/usr/bin/env python 
import platform 
from ctypes import CDLL, c_char_p 

import pkg_resources 

sysname = platform.system() 

if sysname == 'Darwin': 
    lib_name = "libfoo.dylib" 
elif sysname == 'Windows': 
    lib_name = "libfoo.dll" 
else: 
    lib_name = "libfoo.so" 
lib_path = pkg_resources.resource_filename('python_package', 'lib/{}'.format(lib_name)) 
foo = CDLL(lib_path) 

bar = foo.bar 
bar.restype = c_char_p 
bar.argtypes = [c_char_p] 

print(bar('hello')) 

build Rad:

python setup.py bdist_wheel 

Es schafft ein bestimmtes Plateform Rad rtfdoc-0.0.1-cp34-cp34m-macosx_10_10_x86_64.whl und Mac-Anwender können diese Lösung ist nicht ganz zufriedenstellend ein einfaches pip install rtfdoc-0.0.1-cp34-cp34m-macosx_10_10_x86_64.whl

tun:

  • Ich denke, ich werde noch ein Extension oder schauen Sie auf SCons für erstellen müssen Linux-Benutzer.
  • aktualisieren wird mein Paket wegen der Produktion der lib
  • Ich weiß es nicht schwierig sein, wie für 32-Bit-Verwaltung-DLL-und 64-Bit-

Vielen Dank, habe ich viel gelernt, und Ich verstehe, warum setup.py in Kissen oder Psycopg2 riesig sind

2

Sie können cibuildwheel verwenden, um Räder auf Travis CI und/oder Appveyor für alle Arten von Plattformen und Python-Versionen zu bauen. Dieses Tool kann auch Ihre Räder auf PyPI oder anderswo bereitstellen.