Programmierung mit Python

Inhalte

Dieses Seminar hat keinerlei formellen Vorgaben zum Inhalt, das heisst, es sollte genug Zeit bleiben, um auf die spezifischen Bedürfnisse der Teilnehmer einzugehen. Wichtige Inhalte sind unter anderem:

  • Theorie
    • Warum Python
    • Philosophie von Open Source
    • Technisches (Kompilation, Interpretierte Sprache, Bytecode, Plattformunabhängigkeit,...)
    • Lizensierung (GPL, MPL,...)
    • Warum Englisch
    • Python Programme starten
  • Installation von Python (pflicht!)
    • Konfiguration von Python (PATH, PYTHONPATH,...)
    • Installation und Konfiguration von SciTE oder Notepad++
  • Grundlegende Syntax
    • Zeilenumbruch als Ende eines Kommandos
    • Einzuege fuer Blöcke
    • Zuweisung von Variablen
    • Kommentare
  • Typen und Operatoren
  • Höhere Datentypen und Sequenzen
    • Strings (immutable)
    • Tuples (immutable)
    • Listen (mutable)
    • Dictionaries (mutable)
    • Dateien
  • Schleifen und Abfragen (if, while, for,...)
  • Funktionen
  • Module
  • Klassen
  • Exceptions
  • Konvertierung von Typen
    • float(arg)
    • int(arg)
    • str(arg)
  • Debugging
  • wichtige in Python enthaltene Bibliotheken
    • os (Interaktion mit dem Betriebssystem und Plattformunabhängigkeit)
    • sys (Informationen zum Pythoninterpreter, Argumente auslesen)
    • string (Manipulation von Zeichenketten)
    • math (grundlegende mathematische (hauptsächlich trigonometrische) Funktionen)
    • re (reguläre Ausdrücke)
    • ...
  • weitere Bibliotheken, die nicht mit Python mitgeliefert werden (diese werden nur behandelt, wenn ausreichend Zeit übrig ist)
  • Plattformunabhängiges Programmieren
  • Programmierprojekt

Unterrichtsmaterial

Eine Präsentation, die Python und die von Python verwendete Syntax sehr kompakt zusammenfasst steht mit python.pdf zur Verfügung.

Die im Unterricht verwendeten, erklärenden Übungen stehen zum Download bereit:
python_exercise_1.pdf
python_exercise_2.pdf
python_exercise_3.pdf
python_exercise_4.pdf
python_exercise_5.pdf
python_exercise_6.pdf
python_exercise_7.pdf
python_exercise_8.pdf
Der interessierte Leser kann auch den LaTeX Sourcecode der obigen Dateien herunterladen: python_exercises_source.tar.bz2

Tools

pdb - Python Debugger

Python verfügt über mehr als einen bekannten Debugger sowie unterschiedliche Frontends zu diesen. Der Standard - pdb - ist schon bei der Installation von Python dabei und wird mit dem Namen eines Python Moduls aufgerufen:

pdb file.py

Die wichtigesten Kommandos schließen

h(elp)
l(ist) [first [,last]]
b(reak) ([file:]lineno | function) [, condition], cl(ear) [bpnumber [bpnumber...]]
run (restart)
s(tep), n(ext), r(eturn), c(ontinute)

ein. Lokale Variablen können durch Eingabe ihres Namens angezeigt werden, für globale Variablen ist ein ! vorzustellen. Praktisch ist auch das Definieren von Kürzeln für Kommandos:

alias aliasname code

Solche Alias können in der Datei ~/.pdbrc gespeichert werden, damit sie bei jedem Start des Debuggers automatisch zur Verfügung stehen.

Dokumentation von pdb findet sich in der offiziellen Python Dokumentation und in dem Artikel Interactive Debugging with Python.

IPython Shell

IPython bietet gegenüber der regulären Python Shell massive Vorteile, welche Syntax Highlighting, Kommandovervollständigung und die Definition von Makros einschließen. Zuerst muß die Shell installiert werden:

sudo aptitude install ipython

Besonders nützlich ist es, normale Shellbefehle direkt ausführen zu können, indem man einfach ein ! davorstellt. Der Output dieser Kommandos kann auch gespeichert und verwendet werden. Zum Beispiel:

dircontent = !ls -l

Fügt man ein Fragezeichen an das Ende eines Objekts, so bekommt man Hilfe dazu (object inspection):

dir?

Weiters stellt IPython sogenannte "magic functions" zur Verfügung, womit sowohl IPython selbst gesteuert werden kann als auch einige Systembefehle besonders einfach ausführbar sind. Generell werden diese Funktionen mit dem Präfix "%" aufgerufen. Einen Überblick über die vorhandenen magic functions bekommt man mit

%lsmagic

Die Möglichkeiten dieser Funktionen sind sehr weitläufig und schließen persistente Variablen (die Werte bleiben über mehrere IPython Sessions gespeichert), Aliases und die Definition von Makros ein. Detaillierte Hilfe zu den magic functions bekommt man mit dem Befehl

%magic

Besonders nützlich ist auch die Möglichkeit, einen externen Editor zu verwenden. Damit kann nicht nur eine kompliziertere Befehlszeile verfasst werden, sondern auch eine bereits geschriebene Zeile verändert werden. Es wird jener Editor verwendet, der in der Systemvariable $EDIT definiert ist. Der Aufruf dieser Funktion erfolgt mit

%edit [linenumber]

IPython ist über die Datei ~/.ipython/ipythonrc auch sehr gut konfigurierbar. Hilfe zu dem Projekt ist neben der man page auch in der offiziellen IPython Dokumentation zu finden.

GNU Emacs

Emacs bietet (natürlich) auch exzellente Unterstützung für das Schreiben, Testen und Debuggen von Python Programmen. Es gibt unterschiedliche Python Modi - ich empfehle jedoch, jenen aus dem Packet python-mode zusammen mit Emacs zu installieren.

sudo aptitude install emacs python-mode

Python Dateien werden automatisch erkannt und können in Emacs automatisch mit der Tastenkombination [Strg]+[c] [Strg]+[c] ausgeführt werden. Daher ist es praktisch mit Emacs Dinge auszuprobieren, welche für IPython zu groß sind, selbst wenn man Emacs nicht für sein Hauptprojekt verwendet. Die Emacs Speedbar unterstützt Python auch vollständig und erleichtert die Navigation in größeren Projekten. Sie kann mit [Alt]+[x] speedbar aufgerufen werden.

Emacs hat auch ein komfortableres Interface zum Python Debugger pdb. Dieser kann in Emacs mit [Alt]+[x] pdb gestartet werden, wobei im folgenden Dialog die Datei angegeben werden muss, welche untersucht werden soll. Besonders fein ist dabei, dass der jeweils aktuelle Kontext in einem eigenen Emacs Window angezeigt wird, während der Debugger in einem anderen aktiv ist.

Weitere Informationen über die Verwendung von Emacs als (Python) IDE finden sich im Abschnitt Programmiertools.

Testen

Python hilft beim Erstellen von Unittests mit dem unittest Modul. Noch einfacher wird es, wenn das Ausführen von Tests mit dem Packet nosetests automatisiert wird. Es stellt den Befehl nosetests auf der Kommandozeile zur Verfügung, welcher alle Python Dateien in einem gegebenen Verzeichnis und dessen Unterverzeichnissen nach Tests durchsucht und diese ausführt. Zuerst muss dieses installiert werden:

sudo aptitude install python-nose

Es gibt verschiedene Möglichkeiten, nosetests mitzuteilen, welche Klassen Testcases enthalten. Eine einfache Möglichkeit ist es, die Klasse TestCase als Superklasse zu verwenden. Alle Funktionen, deren Name mit "test" beginnt, werden als Testcases behandelt. Die Funktionen setUp und tearDown können wahlweise implementiert werden, um die Testumgebung vor jedem Test zu initialisieren und nach jedem Test aufzuräumen. Das folgende Testmodul zeigt diese Prinzipien:

from unittest import TestCase

class MyTests(TestCase):
    def setUp(self):
        """Executed before every test."""
        pass

    def tearDown(self):
        """Executed after every test."""
        pass

    def testSomething(self):
        self.failUnless(1==1)

    def testFail(self):
        self.failUnlessEqual(1,2)

    def testSomethingElse(self):
        self.failIfEqual(1,3)

Codesnippets

Verzeichnisbaum

Soll eine Aktion für alle Dateien (oder ein bestimmtes Subset dieser) in einem Verzeichnisbaum ausgeführt werden, so hilft Python mit os.walk:

EXTENSIONS = ["txt", "py"]
for root, dirs, files in os.walk(PATH):
    for filename in [f for f in files if f.split(".")[-1].lower() in EXTENSIONS]:
        filepath = os.path.join(root, filename)
        with open(filepath) as f:
            # do something
            pass

Internas

Bevor man aufgrund der teilweise langsamen Performance von Python den Code mittels eines Profilers analysiert und dann mit Tools wie zum Beispiel Cython optimiert, kann man schon beim Schreiben des Prototypen mit dem Wissen über ein paar interne Details von Python einiges an Performance herausholen.

Listen

Intern sind Python Listen nicht verkettete Listen im Sinn der Informatik, sondern eigentlich Arrays (zusammenhängende Blöcke von Speicher). Dadurch ist es der Lese- und Schreibzugriff sehr schnell: O(1). Das Anhängen an eine Liste mittels append ist in der Regel ebenso performant, da stets Speicher für mehr Elemente als notwendig angefordert wird, wodurch ein Umspeichern selten notwendig ist. Teurer ist hingegen das Einfügen an jede andere Position, insbesonders an den Anfang der Liste mit insert(index, object>), da dies stets ein Umspeichern der hinteren Listenelemente erfordert. Wird eine Liste mit einer Schleife von vorne befüllt, so ist es in der Regel viel schneller, die Liste zuerst mittels reverse umzudrehen, die Elemente von hinten hinzuzufügen und nach der Schleife ein weiteres reverse auszuführen.

Performance

Um gute Performance zu gewährleisten, muss man sich schon vor der ersten Codezeile überlegen, welche Algorithmen verwendet werden sollen, um die Komplexität niedrig zu halten. Sollte die Performance eines bereits bestehenden Programms jedoch einmal nicht mehr ausreichen, gibt es zahllose Möglichkeiten, diese zu verbessern. Zuerst sollte der Code stets mittels eines Profilers analysiert werden, um herauszufinden, wo die Flaschenhälse versteckt sind (Hilfe zum Thema Profiling findet sich in der Python Dokumentation). In der Regel kann man dann schon durch Anpassen des reinen Python-Codes (eventuell mittels eines besseren Algorithmus oder durch effizientere Programmierweise) einiges an Beschleunigung herausholen.

Sollte dies jedoch noch nicht ausreichen, so hat man einige Möglichkeiten, auf schnellere Sprachen zurückzugreifen. Der betroffene Code kann entweder in C oder C++ neu geschrieben werden, jedoch müssen danach Python-bindings mittels SWIG erstellt werden. Eine oft einfachere Alternative ist die Verwendung von Cython.

Cython

Cython ist eine eigene Programmiersprache, die einen großen Teil der Flexibilität von Python mit der Performance von C kombiniert. Genaugenommen handelt es sich dabei um einen C Code-Generator, der sich auch automatisch um die Erstellung von Python Bindings kümmert. Zuerst sollten die notwendigen Pakete installiert werden.

sudo aptitude install cython python-dev

Danach besteht der erste Schritt wie erwähnt in der Verwendung eines Profilers, um herauszufinden, welche Funktionen kritisch für die Performance sind. Diese können gegebenenfalls zuerst in reinem Python zu überarbeiten. Nun ist zu entscheiden, ob man ganze Dateien mittels Cython optimieren will oder lediglich einzelne Funktionen. Im ersten Fall müssen die Datei lediglich auf .pyx umbenannt werden. Im letzeren werden die betroffenen Funktionen in eine neue, gesonderte .pyx Datei verschoben und in der ursprünglichen Datei mittels import wieder angeboten. In beiden Fällen entsteht mindestens eine .pyx Datei, welche zuerst teilweise typisiert werden muss, was für die Performancesteigerung ausschlaggebend ist. Cython hilft bei der Erkennung, welche Variable noch nicht typisiert sind mit dem Befehl

cython -a yourfile.pyx

Dies generiert yourfile.html - ein Codelisting, bei dem nicht typisierte Zeilen gelb sind und perfekt typisierte Zeilen weißen Hintergrund haben. Es ist nicht notwenig, dass alle Zeilen weiß werden. Für die Performance ausschlaggebend ist, dass jene Zeilen, die sich in (ev. sogar vernesteten) Schleifen befinden typisiert sind. Informationen zur Typisierung finden sich in der Onlinehilfe von Cython. Sobald man mit der Typisierung fertig ist, muß der C Code erstellt und als Python Extension kompiliert werden. Bei der Verwendung von Python 2.7 geht das in Linux mit

cython yourfile.pyx
gcc -c -fPIC -I/usr/include/python2.7/ -O3 yourfile.c
gcc -shared i6_ctypes.o -O3 -o yourfile.so

Um einiges einfacher und plattformunabhängiger ist die Verwendung eines Python Setup Scripts. Dieses ist im Verzeichnis der .pyx Datei in der Datei setup.py zu speichern.

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("yourfile", ["yourfile.pyx"]),
               ]

setup(
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules,
)

Nachdem alle .pyx Dateien in der ext-modules Liste als Extension eingetragen sind, können die obigen Schritte des Erstellens und Kompilierens des C Codes einfach mittels

python setup.py build_ext --inplace

durchgeführt werden. Insgesamt ist bei geeigneten Funktionen mit Performancesteigerung um mehr als das 100-fache zu rechnen.

Hier folgt eine (unsortierte) Aufstellung einiger der im Kurs gezeigten Webseiten mit Quellen zu Python generell und einigen interessanten Modulen. Diese Webseiten sind ein sehr guter Startpunkt fuer Informationen. Mit den enthaltenen Ressourcen sollte sich beinahe jedes Python Problem lösen lassen. Wenn sie aber nicht ausreichen sollten, so empfehle ich neben einer Recherche mit einer Suchmaschine, sich Newsgroups und SIGs zum Thema anzusehen. Weiters empfiehlt es sich, mindestens ein gutes Lehrbuch und/oder eine Referenz on- oder offline zur Verfügung zu haben. Wenn dennoch alle Stricke reissen gilt: vielleicht sollte man doch einen Menschen fragen ;). Viel Spass beim Coden in Python!

Link kurze Beschreibung
http://python.org/ Englische Seite, von der man nicht nur die aktuellste Version von Python herunterladen kann, sondern auch Tutorials und Dokumentation zur Programmiersprache (in Englisch, Deutsch und vielen anderen Sprachen).
The Python Standard Library (Englische) Referenzdokumentation
IPython Documentation
http://www.rg16.asn-wien.ac.at/~python/literatur.html Links zu Websites über das Programmieren mit Python
http://wiki.python.de/ Das deutschsprachige Python Wiki
[Valid XHTML 1.1!]