Mit Python programmieren

Aus LinuxUser 02/2005

Mit Python programmieren

Flexibles Werkzeug

Trotz grafischer Oberflächen führt manchmal kein Weg am Einsatz von Skripts vorbei, die regelmäßige Aufgaben individuell lösen. Einsteigern bietet sich dafür die klar strukturierte Sprache Python an.

Auf den ersten Blick mag es anachronistisch wirken, den Computer mit kryptischen Textbefehlen zu programmieren. Viele Anwendungen lassen sich jedoch durch Skriptsprachen für den eigenen Bedarf anpassen, ohne dazu gleich ein ganzes Programm zu schreiben.

Sind die ersten Scripting-Hürden überwunden, kann der Anwender seiner Kreativität freien Lauf lassen und dauerhafte Problemlösungen schaffen, die zusätzlich noch befriedigen. Mit Python [1] (siehe Kasten “Der Name”) fällt der Einstieg leicht. Es bietet aber auch Profiprogrammierern durch objektorientierte Features eine Menge Potenzial. Zudem lassen sich auch einige Schwierigkeiten mit Linuxanwendungen lösen: Viele von ihnen sind in Python geschrieben, zum Beispiel der Gnome-Gerätemanager.

Der Name

Mit der gleichnamigen Schlangenfamilie (Python sebae, Python reticulatus, Python regius, …) hat die Programmiersprache nach der Vorstellung ihres Erfinders Guido van Rossum nichts zu tun. Vielmehr bezog er sich bei der Namensgebung auf die britischen Humorkünstler Monty Python (“Das Leben des Brian”). Der ursprünglichen Intention zum Trotz verwenden viele Python-Projekte Schlangen als Maskottchen.

Sprachwahl

Vor der Programmierung stellt sich die Frage nach der richtigen Sprache für den jeweiligen Einsatzzweck. Die Unterschiede zwischen einzelnen Skriptsprachen dabei sind oft kleiner, als ihre jeweiligen Fans behaupten.

Alle Sprachen kennen so genannte Variablen, die Werte aufnehmen, welche sich während der Berechnung ändern. Ob man ihnen einen Wert mit dem Gleichheitszeichen (=) zuweist (Perl, Python) oder über set (Tcl), spielt kaum eine Rolle, wenn man sich erst einmal daran gewöhnt hat.

Die wichtigsten so genannten Kontrollstrukturen finden sich ebenfalls bei den meisten Programmiersprachen. So kommt man kaum ohne eine Fallunterscheidung der Art “wenn das eintrifft, mach dies, sonst jenes” aus. Das Prinzip bleibt dabei stets dasselbe, auch wenn die entsprechenden if-Konstrukte bei Perl und Python leicht unterschiedlich aussehen.

Python starten

Python-Skripts werden vom so genannten Interpreter abgearbeitet. Er liest die Textdatei, übersetzt sie in die Sprache der Maschinen (sozusagen Bits und Bytes) und führt sie auf dem Prozessor aus. Einen separaten Prozess der Übersetzung wie bei C oder C++ gibt es bei solchen Skriptsprachen nicht.

Übergibt man dem Interpreter keine Datei zur Bearbeitung, startet er in einem interaktiven Modus, der auf Eingaben des Benutzer wartet (Abbildung 1). Das bietet sich an, um schnell die Möglichkeiten und die Syntax einzelner Funktionen auszuprobieren.

Abbildung 1: Der Python-Interpreter kennt einen interaktiven Modus, der sich gut zum Ausprobieren eignet.

Abbildung 1: Der Python-Interpreter kennt einen interaktiven Modus, der sich gut zum Ausprobieren eignet.

Geben Sie nach den Größerzeichen help() ein, gelangen Sie in den interaktiven Hilfemodus, in dem jede Eingabe eines Schlüsselworts den Hilfetext anzeigt. Diesen Modus beendet die Tastenkombination [Strg-D], mit der Sie auch den Python-Interpreter verlassen.

Direkt ausführen

Haben Sie ein Python-Programm als Datei gesichert, rufen Sie den Interpreter mit dem Dateinamen als Parameter auf, zum Beispiel python Meinprogramm.py. Alternativ schreiben Sie den Namen des Interpreters in die Datei selbst, unter Verwendung des in der Unix-Kultur bekannten “Shebang” [2], der Zeichenfolge #! in der ersten Zeile des Skripts:

#!/usr/bin/python
print 3 + 4

Dies setzt voraus, dass python sich in /usr/bin befindet. Liegt es woanders, müssen Sie diese Zeile entsprechend anspassen. Alternativ rufen Sie es mit dem Programm env auf. Dann brauchen Sie sich nicht um den exakten Ort zu kümmern, solange python sich im Ausführungspfad PATH befindet: #!/usr/bin/env python,

Besitzt die Skriptdatei die nötigen Rechte (chmod +x Datei), lässt sie sich direkt ausführen. Das obige Beispiel gibt mit dem Befehl print das Ergebnis der Berechnung 3 + 4 aus. Die Kombination von Shebang und Ausführungsrechten funktioniert übrigens auch bei den meisten anderen Skriptsprachen sowie bei Shellskripts.

Vielfalt an Modulen

Der Python-Interpreter selbst kennt nur eine relativ kleine Zahl von Funktionen, wie das oben verwendete print. Für kompliziertere Anwendungen bringt Python eine Menge so genannter Module [3] mit, die jeweils einen bestimmten Anwendungsbereich abdecken, zum Beispiel den Bau von grafischen Benutzeroberflächen, Webprogrammierung oder die Verarbeitung von Zeichenketten (Strings). Im Folgenden sollen einige Module bei der Programmierung eines einfachen Beispielskripts helfen, das Dateinamen mit Leerzeichen oder anderen Linux-untypischen Sonderzeichen in einfachere Namen umbenennt.

Für Funktionen, die betriebssystemabhängige Aspekte wie Pfadnamen oder Umgebungsvariablen betreffen, bringt Python das Modul os[4] mit. Der Befehl import lädt es in ein Skript oder den laufenden Interpreter. Eine grobe Orientierung über die Funktions- und Variablennamen eines Moduls ermöglicht die Methode dir():

>>> import os
>>> dir(os)
… 'waitpid', 'walk', 'write']

Die verkürzt wiedergegebene Ausgabe zeigt einige Methoden des Moduls, die Sie mit dem oben beschriebenen help() weiter erforschen können. Allerdings müssen Sie dabei den Funktionsnamen den Modulnamen voranstellen, damit help sie findet: help(os.unlink). Importieren Sie das Modul mit einer anderen Konstruktion, ändert sich die Namenskonvention: Mit from os import * stehen alle Funktionen des Moduls ohne das os zur Verfügung, also zum Beispiel als listdir() gegenüber os.listdir().

Verloren ohne Doku

Suchen Sie eine bestimmte Funktionalität, ziehen Sie besser direkt die Python-Dokumentation zu Rate. So benötigt das geplante Beispiel eine Methode, um den Inhalt eines Verzeichnisses zu lesen: os.listdir(). Die Hilfe zeigt in diesem Fall, dass die Funktion einen Parameter erwartet, der das Verzeichnis spezifiziert. Die Methode gibt bei ihrem Aufruf einen Wert zurück, den das Programm im Folgenden weiterverarbeiten kann:

dateien = os.listdir(verzeichnis)

Ruft man die Methode auf diese Weise auf, enthält die Variable dateien anschließend die die Datei- und Verzeichnisnamen, die sich in verzeichnis befinden. Die Spezialverzeichnisse . und .. blendet die Funktion von vornherein aus. Das Ergebnis ist eine so genannte Liste (auch Array), eine spezielle Art von Variablen, die recht häufig in Skriptsprachen Verwendung findet. Mit eckigen Klammern greift man auf einzelne Elemente der Liste zu. So enthält dateien[0] den ersten Namen des Verzeichnisses – die Zählung beginnt bei Null.

Zusätzlich bietet Python spezielle Array-Funktionen [5], um einzelne Elemente in Listen zu finden, zu löschen, zu veränderen und so fort. Enthält das Verzeichnis im Beispiel keine Dateien, ist die von listdir() zurückgegebene Liste leer. Die Liste besitzt dann die Länge 0, was sich mit der Methode len() prüfen lässt:

>>> from os import *;
>>> d = listdir('LeeresVerz')
>>> len(d)
0

Existiert das Verzeichnis gar nicht, liefert die Methode eine Fehlermeldung, die der Programmierer abfangen oder behandeln muss (Stichwort Exceptions).

Struktur durch Leerzeichen

Besteht das Programm aus mehreren Zeilen, strukturiert man es im Allgemeinen nach Blöcken, also logisch zusammengehörigen Abschnitten. Hier weist Python eine Besonderheit auf, die es von seinen Kollegen unterscheidet: Es verwendet keine geschweiften Klammern (Perl) oder Schlüsselwörter (Ruby), sondern rückt zusammengehörige Code-Blöcke um dieselbe Anzahl an Leerzeichen ein. Das verdeutlicht der folgende Abschnitt, der zusätzlich eine For-Schleife als Kontrollstruktur einführt.

dateien = os.listdir(verzeichnis)
for datei in dateien:
   print datei

Die Variable dateien enthält nach dem Aufruf von listdir() die Dateinamen in verzeichnis. Die folgende Zeile durchläuft mit for alle Listenelemente und weist dabei jedes Element der Variablen datei zu. Damit tritt das Programm in eine Schleife ein, deren Beginn der Doppelpunkt markiert, und die durch die beschriebene Einrückung festgelegt ist. In diesem Fall handelt es sich nur um die eine Zeile, die den Dateinamen mit print ausgibt. Soll das Skript in der Schleife noch andere Befehle abarbeiten, müssen diese mit derselben Zahl von Leerzeichen eingerückt sein:

for datei in dateien:
   print "Dateiname:"
   print datei

Achten Sie dabei auch auf den Typ von Leerzeichen: Ein Tabulatur entspricht nicht einer gewissen Zahl von einfachen Leerzeichen, auch wenn das Ergebnis im Editor identisch aussieht.

Das bisher geschriebene Programmfragment liest den Inhalt eines Verzeichnisses und durchläuft mit diesem Ergebnis eine Schleife. Bleibt als Restaufgabe nicht mehr zu tun, als in jedem Namen die Sonderzeichen zu suchen und sie durch ein anderes Zeichen zu ersetzen.

Um ein bekanntes Perl-Wort zu übernehmen: Es gibt auch in Python mehr als einen Weg, diese Aufgabe zu lösen [6]. Will man ein solches Skript wirklich narrensicher gestalten, ufert die Programmierung schnell aus. Zum Beispiel könnte man berücksichtigen, in welchem Character-Encoding die Namen auf dem Dateisystem vorliegen.

Der Kürze wegen beschränkt sich das Beispiel auf den einfachen Fall der ASCII-Kodierung und lässt deshalb die Unicode-Eigenheiten der aktuellen Python-String-Klassen [7] unbeachtet.

Um in einer Zeichenkette ein Zeichen zu finden, kennt das String-Modul die Methode find(). Sie versteht bis zu drei Parameter, von denen der obligatorische natürlich das gesuchte Zeichen ist.

>>> dateiname = "home.html"
>>> dateiname.find('h')
0

Die Funktion gibt nur die erste Fundstelle des gesuchten Zeichens an. Um weitere zu finden, muss man die Suche also hinter der ersten Fundstelle fortsetzen. Dazu dienen die beiden restlichen Parameter von find(). Sie geben optional den Suchbeginn oder den Suchbereich in der so genannten Slice-Notation an: Wie oben anhand der Listen beschrieben, dienen eckige Klammern dazu, auf einzelne Elemente zuzugreifen. Mit einem Doppelpunkt und einer zweiten Zahl wird daraus ein Abschnitt mehrerer Zeichen, eben ein Slice. Dabei zählt die zweite Zahl nicht mehr zum Slice. So steht dateiname[3:5] für die Folge des vierten bis fünften Zeichens (Erinnerung: die Zählung beginnt bei Null):

>>> dateiname = "home.html"
>>> dateiname[3:5]
'e.'

Die obige Suche lässt sich damit folgendermaßen erweitern:

>>> dateiname = "home.html"
>>> dateiname.find('h')
0
>>> dateiname.find('h', 1)
5

Findet die Funktion das Zeichen nicht, gibt sie -1 zurück. Das Beispiel demonstriert außerdem die objektorientierte Syntax Pythons: Die Methode find() existiert nicht einfach als solche im luftleeren Raum, sondern gehört zu einem String-Objekt. Um sie aufzurufen, muss in einem Programm also erst ein String-Objekt existieren, hinter man dem mit einem Punkt getrennt die Methode aufruft.

Praktischerweise enthält Pythons String-Modul schon eine Funktion, die selbständig alle Vorkommen eines Zeichens findet und sogar durch ein anderes ersetzt: replace().

>>> datei = "mit zwei blanks"
>>> neu = datei.replace(' ', '_')
>>> print neu
mit_zwei_blanks

Nun bleibt nicht mehr zu tun, als das File auf dem Dateisystem tatsächlich umzubenennen. Das übernimmt die Methode rename() aus dem Modul os. Als Parameter benötigt sie – wie zu erwarten – den alte und den neuen Dateinamen.

In der bisherigen Version benennt das Skript nur Dateien in einem im Skript festgelegten Verzeichnis um. Sinnvoller ist es aber, das Verzeichnis als Kommandozeilenparameter vorzusehen. Viele Skriptprogramme arbeiten einem solchen Falll nach folgendem Prinzip:

  • Prüfen ob es Parameter gibt.
  • Falls ja und die Werte vernünftig sind, verwende sie.
  • Falls nein, verwende im Skript festgelegte Voreinstellungen.

Solche Parameter verarbeiten Python-Programmierer mit dem Modul sys und dessen Variablen argv, einer Liste. Das erste Element der Liste ist der Name des Skript selbst, die Liste besitzt also immer mindestens ein Element. Um das Vorhandensein von Parametern zu testen, prüft man also, ob die Liste mehr als ein Element hat:

if len(sys.argv) > 1:
  verzeichnis = sys.argv[1]
else:
  verzeichnis = "."

Mit dieser Fallunterscheidung bearbeitet das Skript ohne Parameter das Skript das aktuelle Verzeichnis.

Der einfache Umbenenner für seltsame Dateinamen ist damit fertig programmiert. Um das Programm wirklich nützlich zu machen, fehlen allerdings noch einige Features. So verzichtet es völlig auf die Behandlung von Fehlern – unter diesem Aspekt sicher ein schlechtes Beispiel. Absehbare Fehlerquellen sind zum Beispiel gleichlautende Dateinamen nach dem Umbenennen oder unzureichende Dateirechte. Einige Fehler ließen sich dadurch abfangen, dass das Skript den Rückgabewert einzelner Methoden überprüft.

Der unter Python übliche Weg ist, dafür Exceptions zu verwenden. Dazu schließt man Zeilen mit möglichen Fehlerquellen in einen Block ein, der mit dem Schlüsselwort try markiert ist. Danach folgt ein zweiter mit except marktierter Block zur Fehlerbehandlung. Tritt bei der Abarbeitung des ersten Blocks ein Fehler auf, springt der Python-Interpreter in den Except-Block, wo das Skript wie vom Programmierer vorgesehen mit dem Fehler umgeht. Im Skript auf der Heft-CD finden Sie dazu ein Beispiel.

Damit sind die wichtigsten Sprachkonstrukte vorgestellt, um in Python einzusteigen. Weitere Einführungen finden sich auf der Python-Website. Einige englischsprachige Bücher sind online frei zugänglich, zum Beispiel Dive Into Python [8] oder für Fortgeschrittene Thinking in Python [9]. Beide Bücher und die offizielle Python-Dokumentation finden Sie auch auf der Heft-CD. Freie deutschsprachige Dokumentation ist rar, eine kurze Liste liefert [10]. Der beste Weg, eine Programmiersprache zu lernen ist in jedem Fall, darin möglichst viel zu programmieren.

Glossar

Syntax

Mehr oder weniger synonym zu Grammatik. Die Syntax einer Sprache (egal ob menschlicher oder für Computer) legt fest, welche Elemente in welcher Anordnung einen zulässigen “Satz” ergeben. So steht im Deutschen der Artikel immer vor einem Substantiv, in Python fängt eine Fallunterscheidung immer mit einem if an.

Character-Encoding

Zeichen ist nicht gleich Zeichen: Es gibt buchstäblich tausende von Möglichkeiten, ein Zeichen computerintern zu repräsentieren. Die bekannteste Möglichkeit stellt wohl der ASCII-Code dar, der einem Zeichen eine Zahl zwischen 0 und 127 zuordnet. In Zukunft werden die meisten Systeme Unicode verwenden, das wiederum einige Varianten zur Speicherung kennt, zum Beispiel UTF-8, bei dem zwei Zahlen (Bytes) für ein Zeichen stehen.

Infos

[1] Python-Homepage: http://www.python.org

[2] Was ist ein “Shebang”?: http://de.wikipedia.org/wiki/Shebang

[3] Modul-Referenz: http://www.python.org/doc/2.4/lib/lib.html

[4] OS-Modul: http://www.python.org/doc/2.4/lib/module-os.html

[5] Listen verarbeiten: http://www.python.org/doc/2.4/lib/typesseq-mutable.html

[6] There’s more than one way to do it: http://www.maths.adelaide.edu.au/~cmc/tutorials/perlintro/x175.html

[7] String-Methoden: http://www.python.org/doc/2.4/lib/string-methods.html

[8] Online-Buch “Dive Into Python”: http://diveintopython.org

[9] Online-Buch “Thinking in Python”: http://www.mindview.net/Books/TIPython

[10] Links zu deutschsprachiger Python-Dokumentation: http://www.python.org/doc/NonEnglish.html#german

LinuxUser 02/2005 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben