Der Eierkocher Das distutils & setuptools Rezeptbuch Autor: Datum: Revision: Christopher Arndt 2010-09-09 466 Abstract Dies ist eine Sammlung von nützlichen Rezepten, mit Hilfe derer man seine Pythonprojekte für die Verteilung und Installation via distutils und setuptools einrichtet. This is a collection of useful recipes to make your Python projects ready for distribution and installation via distutils and setuptools. Inhalt Einführung Ein Pythonprojekt für distutils einrichten Rezept Nr. 1: paketlose Pythonmodule #1 Rezept Nr. 2: paketlose Pythonmodule #2 Rezept Nr. 3: Pythonpakete Rezept Nr. 4: C-Extensionmodule für distutils einrichten Rezept Nr. 5: Ein Projekt auf PyPI registrieren Rezept Nr. 6: Ein Pythonprojekt für setuptools einrichten Sourcedistributionen und Eggs erstellen Rezept Nr. 7: Sourcedistributionen Rezept Nr. 8: Egg-Distributionen Rezept Nr. 9: Sourcedistributionen und Eggs auf PyPI hochladen Rezept Nr 10: Sonstige Tipps und Tricks zum Umgang mit setuptools Rezept nr. 11: Einbindung von Testsuites in setup.py Zukünftige Rezepte Verweise 1 Einführung Funktionen von distutils: • Source- und Binarydistributionen für Pythonmodule und -pakete erstellen • C-Extensions kompilieren (à la make) • Pythonmodule und -pakete installieren • Metadaten von Paketdistributionen verwalten • Projekte auf PyPI registrieren und Distributionen hochladen Funktionen von setuptools: • Egg-Distributionen erstellen • Paketabhängigkeiten verwalten • Pakete auf PyPI und anderswo finden und herunterladen (easy_install) • Egg-Distribution und Abhängigkeiten installieren (multiversionsfähig) • diverse distutils Erweiterungen • u.v.m. Ein Pythonprojekt für distutils einrichten Rezept Nr. 1: paketlose Pythonmodule #1 Beispielprojekt: recipes/recipe01/ setup.py von Beispielprojekt recipe01: #!/usr/bin/env python from distutils.core import setup setup( name = ’datehelper’, version = ’1.0’, description = ’A simple module with helper functions for handling dates’, author = ’Christopher Arndt’, author_email = ’[email protected]’, url = ’http://chrisarndt.de/talks/cooking-eggs/’, py_modules = [’date’], ) Das Argument py_modules listet alle Pythonmodule auf, die zur Distribution gehören. Diese werden bei der Installation normalerweise direkt in das site-packages-Verzeichnis der systemweiten Pythoninstallation kopiert. 2 Rezept Nr. 2: paketlose Pythonmodule #2 Beispielprojekt: recipes/recipe02/ Für jedes aufgelistete Modul muss eine entsprechende Pythonmoduldatei relativ zum Verzeichnis von setup.py vorhanden sein. Oder das Verzeichnis, in dem die Moduldateien liegen, muss mit dem package_dir-Argument angegeben werden. Weitere Beispiele: py_modules = [’foo’, ’util’, ’versioninfo’] package_dir = {’’: ’src’} py_modules = [’foo’] Weiterführende Dokumentation: • http://docs.python.org/distutils/setupscript.html#listing-individual-modules Rezept Nr. 3: Pythonpakete Beispielprojekt: recipes/recipe03/ Sobald das Projekt mehrere Pythonmodule hat, ist es sinnvoll, diese in einem Pythonpaket zu organisieren. Danach muss setup.py angepasst werden. Man kann entweder einzelne Module separat auflisten: py_modules = [’pkg1.foo’, ’pkg2.bar’, ’api’] Bei diesem Beispiel müssen die Module in folgender Verzeichnisstruktur vorliegen: <project>/ pkg1/ __init__.py foo.py pkg2/ __init__.py bar.py api.py setup.py Oder man kann einfach alle Pakete mit dem packages-Argument auflisten: packages = [’pkg1’, ’pkg2’] Jedes aufgelistete Paketverzeichnis muss eine __init__.py Datei enthalten. Auch hier kann wieder package_dir verwendet werden, um die Verzeichnisstruktur des Projekts anzupassen: package_dir = {’’: ’src’} packages = [’pkg1’, ’pkg2’] setup.py von Beispielprojekt recipe03: 3 #!/usr/bin/env python from distutils.core import setup setup( name = ’datehelper’, version = ’1.2’, description = ’A simple module with helper functions for handling dates’, author = ’Christopher Arndt’, author_email = ’[email protected]’, url = ’http://chrisarndt.de/talks/cooking-eggs/’, packages = [’date’], ) Weiterführende Dokumentation: • http://docs.python.org/distutils/setupscript.html#listing-whole-packages Rezept Nr. 4: C-Extensionmodule für distutils einrichten Beispielprojekt: recipes/recipe04/ C-Extensionmodule, die als Sourcecode vorliegen, können von distutils bei der Installation automatisch kompiliert werden. Dazu müssen die Extensionmodule in setup.py folgendermaßen deklariert werden. setup.py von Beispielprojekt recipe04: from distutils.core import Extension, setup setup( name = ’datehelper’, version = ’1.3’, description = ’A simple module with helper functions for handling dates’, author = ’Christopher Arndt’, author_email = ’[email protected]’, url = ’http://chrisarndt.de/talks/cooking-eggs/’, packages = [’date’], ext_modules = [Extension(’date.time’, [’date/time.c’])] ) Beachte, dass die Extension-Klasse zusätzlich importiertwerden muss und dass das ext_modulesArgument eine Liste von Instanzen dieser Klasse erwartet. Werden für die Kompilierung zusätzlich (Pre-)Compiler- oder Linkerflags benötigt, können diese auf folgende Weise angegeben werden: 4 setup( ..., ext_modules = [ Extension(...., define_macros=[(’NDEBUG’, ’1’), (’POSIX’, ’None’)], include_dirs=[’/usr/include/X11’], library_dirs=[’/usr/X11R6/lib’], libraries=[’X11’, ’Xt’], extra_compile_args = [’-03’], extra_link_args = [’...’] ) ] ) Weiterführende Dokumentation: • http://docs.python.org/extending/extending.html • http://docs.python.org/distutils/setupscript.html#describing-extension-modules Rezept Nr. 5: Ein Projekt auf PyPI registrieren Beispielprojekt: recipes/recipe05/ • Zunächst muss ein PyPI-Account auf http://pypi.python.org/ erstellt werden. • Danach sollte man überprüfen, ob alle Metadaten des Projekts in der setup.py vollständig und aktuell sind, insbesondere die Versionsnummer, description. • Ggf. long_description, URLs und classifiers-Kategorien ergänzen. gültiger Kategorien findet man auf der PyPI-Webseite. Eine Liste Der Registrierungvorgang ist einfach. Im Verzeichnis, in dem die setup.py-Datei des Projekts liegt, folgende Shell-Komamndos ausführen: $ python setup.py register Danach sollte das Projekt unter http://pypi.python.org/pypi/<project> mit Beschreibung, URLs usw. aufgeführt sein. Weiterführende Dokumentation: • http://wiki.python.org/moin/CheeseShopTutorial 5 Rezept Nr. 6: Ein Pythonprojekt für setuptools einrichten Beispielprojekt: recipes/recipe06/ Wenn ein Projektzusätzlich für setuptools eingerichtet wird, lassen sich u.a. auch EggDistributionen erstellen und Abhängigkeiten zu anderen Distributionen deklarieren. setup.py von Beispielprojekt recipe04 (Auszug): #!/usr/bin/env python try: import ez_setup ez_setup.use_setuptools() from setuptools import setup except: from distutils.core import setup from distutils.core import Extension setup( name = ’datehelper’, version = ’1.5’, ... ) Wenn die Distribution nun von den Sourcen mit ‘ python setup.py install‘ installiert wird, wird setuptools, falls es beim Benutzer noch nicht vorhanden ist, automatisch heruntergeladen. Falls dies auch schiefläuft, wird weiterhin distutils benutzt, so dass der Beutzer die Distribution auch notfalls ohne setuptools installieren kann. Dies funktioniert natürlich nur so lange wie der Aufruf von setup() kompatibel mit distutils bleibt. Die Instalation erzeugt nun ein versioniertes Python-Egg, dass in das Python site-packagesVerzeichnis installiert wird. Falls die Distribution C-Extensionmodule enthält, ist das Egg plattformspezisch, da es vorkompilierte Binärmodule enthält. Dadurch bracuht der Benutzer zur Installtion keinen Compiler. Weiterführende Dokumentation: • http://peak.telecommunity.com/DevCenter/setuptools Sourcedistributionen und Eggs erstellen Rezept Nr. 7: Sourcedistributionen Für ein für distutils vorbereitetes Projekt kann folgendermaßen eine Sourcedistribution in verschiedenen Archivformaten erstellt werden: $ python setup.py sdist --formats=zip,gztar,bztar Die Distributionsarchive werden im Unterverzeichnis dist erstellt. Die Dateinamen der Archive setzen sich aus dem Projektnamen und der Versionsnummer, die in setup.py eingetragen sind, zusammen. 6 Rezept Nr. 8: Egg-Distributionen Will man eine Egg-Dsitribution erstellen, ohne sie zu installieren kann man folgendes Kommando benutzen: $ python setup.py bdist_egg Die Egg-Dateien werden ebenso im dist-Unterverzeichnis abgelegt. Rezept Nr. 9: Sourcedistributionen und Eggs auf PyPI hochladen Egg-Distribution erstellen und hochladen: python setup.py bdist_egg upload Source-Distributionen erstellen und hochladen: python setup.py sdist --formats=zip,gztar,bztar upload Rezept Nr 10: Sonstige Tipps und Tricks zum Umgang mit setuptools Beispielprojekt: recipes/recipe10/ • Projekte im “Entwicklungsmodus” installieren (python setup.py develop) • Entwicklungs- und Release-Versionen (setup.cfg) • setup.py-Kommando Shortcuts (setup.cfg) Rezept nr. 11: Einbindung von Testsuites in setup.py Noch nicht ganz fertig... setup( ..., test_suite = ’nose.collector’, ) Zukünftige Rezepte • Abhängigkeiten von anderen Distributionen • Kommandozeilenskripte installieren • Daten außerhalb von Paketen in Eggs kopieren • Plug-ins mit setuptools Entry-Points 7 Verweise SVN-Repository mit den Beispielprojekten und die ReST-Sourcen für diesen Text ausschecken: $ svn co svn://svn.chrisarndt.de/talks/cooking-eggs Online-Version dieses Texts und die Distributionspakete für die Beispielprojekte: http://chrisarndt.de/talks/cooking-eggs 8