| Autor: | Christopher Arndt |
|---|---|
| Datum: | 2010-09-09 |
| Revision: | 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
Funktionen von distutils:
Funktionen von setuptools:
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 = 'chris@chrisarndt.de',
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.
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']
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:
#!/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 = 'chris@chrisarndt.de',
url = 'http://chrisarndt.de/talks/cooking-eggs/',
packages = ['date'],
)
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 = 'chris@chrisarndt.de',
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_modules-Argument 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:
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 = ['...']
)
]
)
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.
Wenn ein Projektzusätzlich für setuptools eingerichtet wird, lassen sich u.a. auch Egg-Distributionen 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-packages-Verzeichnis 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.
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.
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.
python setup.py bdist_egg upload
python setup.py sdist --formats=zip,gztar,bztar upload
Noch nicht ganz fertig...
setup(
...,
test_suite = 'nose.collector',
)
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