FAQ zu Bibliothek und Erweiterungen¶
Allgemeine Fragen zur Bibliothek¶
Wie finde ich ein Modul oder eine Anwendung für Aufgabe X?¶
Sieh in der Bibliotheksreferenz nach, ob es ein passendes Modul der Standardbibliothek gibt. (Irgendwann weißt du, was in der Standardbibliothek steckt, und kannst diesen Schritt überspringen.)
Für Pakete von Dritten suche im Python Package Index oder versuche es mit Google oder einer anderen Suchmaschine. Nach „Python“ plus einem oder zwei Stichwörtern zu deinem Thema zu suchen findet meist etwas Hilfreiches.
Wo ist die Quelldatei math.py (socket.py, regex.py und so weiter)?¶
Findest du für ein Modul keine Quelldatei, ist es vielleicht ein integriertes oder dynamisch geladenes Modul, das in C, C++ oder einer anderen kompilierten Sprache umgesetzt ist. In diesem Fall hast du die Quelldatei möglicherweise nicht, oder sie heißt etwa mathmodule.c und liegt irgendwo in einem C-Quellverzeichnis und nicht im Python-Pfad.
Es gibt (mindestens) drei Arten von Modulen in Python:
Module, die in Python geschrieben sind (.py);
Module, die in C geschrieben und dynamisch geladen werden (.dll, .pyd, .so, .sl und so weiter);
Module, die in C geschrieben und mit dem Interpreter gebunden sind. Um eine Liste davon zu bekommen, gib ein:
import sys print(sys.builtin_module_names)
Wie mache ich ein Python-Skript unter Unix ausführbar?¶
Du musst zwei Dinge tun: Der Modus der Skriptdatei muss ausführbar sein, und die erste Zeile muss mit #! beginnen, gefolgt vom Pfad des Python-Interpreters.
Das Erste erledigst du mit chmod +x scriptfile oder vielleicht chmod 755 scriptfile.
Das Zweite geht auf mehrere Weisen. Am geradlinigsten ist es,
#!/usr/local/bin/python
als allererste Zeile deiner Datei zu schreiben, mit dem Pfadnamen, unter dem der Python-Interpreter auf deiner Plattform installiert ist.
Soll das Skript unabhängig davon sein, wo der Python-Interpreter liegt, kannst du das Programm env verwenden. Fast alle Unix-Varianten unterstützen das Folgende, sofern der Python-Interpreter in einem Verzeichnis im PATH des Benutzers liegt:
#!/usr/bin/env python
Mach das nicht bei CGI-Skripten. Die Variable PATH ist für CGI-Skripte oft sehr knapp gehalten, du musst deshalb den tatsächlichen absoluten Pfadnamen des Interpreters verwenden.
Gelegentlich ist die Umgebung eines Benutzers so voll, dass das Programm /usr/bin/env scheitert, oder es gibt überhaupt kein env-Programm. In diesem Fall kannst du den folgenden Trick versuchen (von Alex Rezinsky):
#! /bin/sh
""":"
exec python $0 ${1+"$@"}
"""
Der kleine Nachteil ist, dass dies die __doc__-Zeichenkette des Skripts festlegt. Das kannst du aber beheben, indem du
__doc__ = """...Whatever..."""
Gibt es ein curses/termcap-Paket für Python?¶
Für Unix-Varianten: Die Standard-Quellcode-Distribution von Python bringt im Unterverzeichnis Modules ein curses-Modul mit, das allerdings nicht standardmäßig kompiliert wird. (Beachte, dass es in der Windows-Distribution nicht verfügbar ist – es gibt kein curses-Modul für Windows.)
Das Modul curses unterstützt die grundlegenden curses-Funktionen sowie viele zusätzliche Funktionen aus ncurses und SYSV-curses, etwa Farben, alternative Zeichensätze, Pads und Mausunterstützung. Das bedeutet, dass das Modul mit Betriebssystemen nicht kompatibel ist, die nur BSD-curses haben, aber es scheint derzeit keine gepflegten Betriebssysteme zu geben, die in diese Kategorie fallen.
Gibt es in Python eine Entsprechung zu onexit() aus C?¶
Das Modul atexit stellt eine Funktion register bereit, die onexit() aus C ähnelt.
Warum funktionieren meine Signalbehandler nicht?¶
Das häufigste Problem ist, dass der Signalbehandler mit der falschen Argumentliste deklariert ist. Er wird so aufgerufen:
handler(signum, frame)
er sollte also mit zwei Parametern deklariert werden:
def handler(signum, frame):
...
Häufige Aufgaben¶
Wie teste ich ein Python-Programm oder einen Bestandteil davon?¶
Python bringt zwei Testframeworks mit. Das Modul doctest findet Beispiele in den Docstrings eines Moduls und führt sie aus, wobei es die Ausgabe mit der im Docstring angegebenen erwarteten Ausgabe vergleicht.
Das Modul unittest ist ein aufwendigeres Testframework, nachempfunden den Testframeworks von Java und Smalltalk.
Um das Testen zu erleichtern, solltest du in deinem Programm einen guten modularen Entwurf verwenden. Dein Programm sollte fast alle Funktionalität in Funktionen oder Klassenmethoden kapseln – und das hat manchmal den überraschenden und erfreulichen Effekt, dass das Programm schneller läuft, weil Zugriffe auf lokale Variablen schneller sind als auf globale. Außerdem sollte das Programm es vermeiden, von veränderten globalen Variablen abzuhängen, denn das macht das Testen viel schwieriger.
Die „globale Hauptlogik“ deines Programms darf so einfach sein wie
if __name__ == "__main__":
main_logic()
am Ende des Hauptmoduls deines Programms.
Sobald dein Programm als überschaubare Sammlung von Funktions- und Klassenverhalten organisiert ist, solltest du Testfunktionen schreiben, die diese Verhalten durchlaufen. Jedem Modul lässt sich eine Testsammlung zuordnen, die eine Folge von Tests automatisiert. Das klingt nach viel Arbeit, ist aber überraschend leicht, weil Python so knapp und flexibel ist. Du kannst das Programmieren viel angenehmer und unterhaltsamer machen, indem du deine Testfunktionen parallel zum „produktiven Code“ schreibst, denn so lassen sich Fehler und sogar Entwurfsschwächen früher finden.
„Hilfsmodule“, die nicht als Hauptmodul eines Programms gedacht sind, dürfen einen Selbsttest des Moduls enthalten.
if __name__ == "__main__":
self_test()
Selbst Programme, die mit komplexen externen Schnittstellen arbeiten, lassen sich testen, wenn die externen Schnittstellen nicht verfügbar sind, indem man „falsche“ Schnittstellen verwendet, die in Python umgesetzt sind.
Wie erzeuge ich aus Docstrings Dokumentation?¶
Das Modul pydoc kann aus den Docstrings in deinem Python-Quellcode HTML erzeugen. Eine Alternative, um API-Dokumentation ausschließlich aus Docstrings zu erzeugen, ist epydoc. Auch Sphinx kann Inhalte aus Docstrings einbeziehen.
Wie bekomme ich einzelne Tastendrücke?¶
Für Unix-Varianten gibt es mehrere Lösungen. Mit curses geht das geradeheraus, aber curses ist ein recht umfangreiches Modul, in das man sich einarbeiten muss.
Threads¶
Wie programmiere ich mit Threads?¶
Verwende unbedingt das Modul threading und nicht das Modul _thread. Das Modul threading baut bequeme Abstraktionen auf den grundlegenden Mitteln auf, die das Modul _thread bereitstellt.
Wie verteile ich Arbeit auf eine Reihe von Arbeiter-Threads?¶
Am einfachsten geht das mit dem Modul concurrent.futures, insbesondere mit der Klasse ThreadPoolExecutor.
Oder du schreibst deine eigene Logik von Hand, wenn du die Verteilung genau steuern willst. Erzeuge mit dem Modul queue eine Warteschlange, die eine Liste von Aufträgen enthält. Die Klasse Queue führt eine Liste von Objekten und hat eine Methode .put(obj), die Elemente zur Warteschlange hinzufügt, sowie eine Methode .get(), die sie zurückgibt. Die Klasse kümmert sich um die nötige Sperrung, damit jeder Auftrag genau einmal ausgegeben wird.
Hier ein einfaches Beispiel:
import threading, queue, time
# Der Arbeiter-Thread holt Aufträge aus der Warteschlange. Ist sie leer,
# nimmt er an, dass keine Arbeit mehr kommt, und beendet sich.
# (In der Praxis laufen Arbeiter, bis sie beendet werden.)
def worker():
print('Running worker')
time.sleep(0.1)
while True:
try:
arg = q.get(block=False)
except queue.Empty:
print('Worker', threading.current_thread(), end=' ')
print('queue empty')
break
else:
print('Worker', threading.current_thread(), end=' ')
print('running with argument', arg)
time.sleep(0.5)
# Warteschlange erzeugen
q = queue.Queue()
# einen Vorrat von 5 Arbeitern starten
for i in range(5):
t = threading.Thread(target=worker, name='worker %i' % (i+1))
t.start()
# beginnen, Arbeit in die Warteschlange zu legen
for i in range(50):
q.put(i)
# den Threads Zeit zum Laufen geben
print('Main thread sleeping')
time.sleep(5)
Ausgeführt ergibt das die folgende Ausgabe:
Running worker
Running worker
Running worker
Running worker
Running worker
Main thread sleeping
Worker <Thread(worker 1, started 130283832797456)> running with argument 0
Worker <Thread(worker 2, started 130283824404752)> running with argument 1
Worker <Thread(worker 3, started 130283816012048)> running with argument 2
Worker <Thread(worker 4, started 130283807619344)> running with argument 3
Worker <Thread(worker 5, started 130283799226640)> running with argument 4
Worker <Thread(worker 1, started 130283832797456)> running with argument 5
...
Weitere Einzelheiten stehen in der Dokumentation des Moduls. Die Klasse Queue bietet eine reichhaltige Schnittstelle.
Welche Arten der Änderung globaler Werte sind thread-sicher?¶
Intern wird ein global interpreter lock (GIL) verwendet, um sicherzustellen, dass immer nur ein Thread in der Python-VM läuft. Im Allgemeinen wechselt Python nur zwischen Bytecode-Anweisungen den Thread. Wie häufig es wechselt, lässt sich über sys.setswitchinterval() einstellen. Jede Bytecode-Anweisung und damit aller von ihr erreichte C-Code ist aus Sicht eines Python-Programms deshalb atomar.
Theoretisch bedeutet das, dass eine genaue Abrechnung ein genaues Verständnis der Bytecode-Umsetzung der PVM erfordert. In der Praxis bedeutet es, dass Operationen auf gemeinsam genutzten Variablen integrierter Datentypen (ints, Listen, Dictionarys und so weiter), die „atomar aussehen“, es wirklich sind.
Zum Beispiel sind die folgenden Operationen alle atomar (L, L1, L2 sind Listen, D, D1, D2 sind Dictionarys, x, y sind Objekte, i, j sind ints):
L.append(x)
L1.extend(L2)
x = L[i]
x = L.pop()
L1[i:j] = L2
L.sort()
x = y
x.field = y
D[x] = y
D1.update(D2)
D.keys()
Diese nicht:
i = i+1
L.append(L[-1])
L[i] = L[j]
D[x] = D[x] + 1
Operationen, die andere Objekte ersetzen, können die Methode __del__() dieser anderen Objekte auslösen, sobald deren Referenzzähler null erreicht, und das kann sich auswirken. Besonders gilt das für Massenaktualisierungen von Dictionarys und Listen. Im Zweifel: nimm einen Mutex!
Können wir den Global Interpreter Lock nicht loswerden?¶
Der global interpreter lock (GIL) wird oft als Hindernis für den Einsatz von Python auf hochwertigen Mehrprozessor-Servern gesehen, denn ein Python-Programm mit mehreren Threads nutzt tatsächlich nur eine CPU, weil (fast) aller Python-Code nur laufen darf, solange der GIL gehalten wird.
Since Python 3.13, CPython provides an optional free-threaded build that can run with the GIL disabled, allowing Python threads to run in parallel on multiple CPU cores (see PEP 703). Free-threaded Python is officially supported as of Python 3.14 (see PEP 779), but is not the default build. See Unterstützung von freiem Threading in Python for details.
The presence of the GIL in current Python releases
doesn’t mean that you can’t make good use of Python on multi-CPU machines!
You just have to be creative with dividing the work up between multiple
processes rather than multiple threads. The
ProcessPoolExecutor class in the
concurrent.futures module provides an easy way of doing so; the
multiprocessing module provides a lower-level API in case you want
more control over dispatching of tasks.
Der umsichtige Einsatz von C-Erweiterungen hilft ebenfalls. Verwendest du eine C-Erweiterung für eine zeitaufwendige Aufgabe, kann die Erweiterung den GIL freigeben, während der Ausführungsfaden im C-Code ist, und anderen Threads so erlauben, etwas Arbeit zu erledigen. Einige Module der Standardbibliothek wie zlib und hashlib machen das bereits.
An alternative approach to reducing the impact of the GIL is
to make the GIL a per-interpreter-state lock rather than truly global.
This was first implemented in Python 3.12 and is
available in the C API. Python interfaces were added in Python 3.14 through the
concurrent.interpreters module and the
InterpreterPoolExecutor class.
The main limitation to it at the moment is likely to be 3rd party extension
modules, since these must be written with multiple interpreters in mind in
order to be usable, so many older extension modules will not be usable.
Ein- und Ausgabe¶
Wie lösche ich eine Datei? (Und andere Fragen zu Dateien …)¶
Verwende os.remove(filename) oder os.unlink(filename). Die Dokumentation dazu steht beim Modul os. Die beiden Funktionen sind identisch, unlink() ist einfach der Name des Unix-Systemaufrufs für diese Funktion.
Um ein Verzeichnis zu entfernen, verwende os.rmdir(), zum Anlegen os.mkdir(). os.makedirs(path) legt alle Zwischenverzeichnisse in path an, die noch nicht vorhanden sind. os.removedirs(path) entfernt Zwischenverzeichnisse, solange sie leer sind. Willst du einen ganzen Verzeichnisbaum samt Inhalt löschen, verwende shutil.rmtree().
Um eine Datei umzubenennen, verwende os.rename(old_path, new_path).
Um eine Datei abzuschneiden, öffne sie mit f = open(filename, "rb+") und verwende f.truncate(offset). Voreingestellt ist offset die aktuelle Position des Lesezeigers. Für Dateien, die mit os.open() geöffnet wurden, gibt es außerdem os.ftruncate(fd, offset), wobei fd der Dateideskriptor ist, also eine kleine ganze Zahl.
Das Modul shutil enthält außerdem eine Reihe von Funktionen für die Arbeit mit Dateien, darunter copyfile(), copytree() und rmtree().
Wie kopiere ich eine Datei?¶
Das Modul shutil enthält eine Funktion copyfile(). Beachte, dass sie auf NTFS-Datenträgern unter Windows keine alternativen Datenströme kopiert und auf HFS+-Datenträgern unter macOS keine Ressourcenzweige, auch wenn beides inzwischen selten verwendet wird. Sie kopiert außerdem keine Dateirechte und Metadaten, wobei shutil.copy2() davon das meiste erhält, wenn auch nicht alles.
Wie lese oder schreibe ich Binärdaten?¶
Um komplexe Binärdatenformate zu lesen oder zu schreiben, verwendest du am besten das Modul struct. Es erlaubt dir, eine Zeichenkette mit Binärdaten zu nehmen, meist Zahlen, und sie in Python-Objekte umzuwandeln — und umgekehrt.
Der folgende Code liest zum Beispiel zwei 2-Byte-Ganzzahlen und eine 4-Byte-Ganzzahl im Big-Endian-Format aus einer Datei:
import struct
with open(filename, "rb") as f:
s = f.read(8)
x, y, z = struct.unpack(">hhl", s)
Das ‚>‘ in der Formatzeichenkette erzwingt Big-Endian-Daten. Der Buchstabe ‚h‘ liest eine „short integer“ (2 Byte) und ‚l‘ eine „long integer“ (4 Byte) aus der Zeichenkette.
Für gleichmäßigere Daten, etwa eine Liste aus durchweg ints oder floats, kannst du auch das Modul array verwenden.
Ich kann os.read() offenbar nicht auf einer mit os.popen() erzeugten Pipe verwenden. Warum?¶
os.read() ist eine Funktion auf niedriger Ebene, die einen Dateideskriptor nimmt, also eine kleine ganze Zahl, die die geöffnete Datei darstellt. os.popen() erzeugt ein Dateiobjekt auf höherer Ebene, denselben Typ, den die integrierte Funktion open() zurückgibt. Um also n Byte aus einer mit os.popen() erzeugten Pipe p zu lesen, musst du p.read(n) verwenden.
Wie greife ich auf die serielle Schnittstelle (RS232) zu?¶
Für Win32, OSX, Linux, BSD, Jython, IronPython:
Für Unix siehe einen Usenet-Beitrag von Mitch Chapman:
Warum schließt das Schließen von sys.stdout (stdin, stderr) es nicht wirklich?¶
Dateiobjekte in Python sind eine Abstraktionsschicht auf höherer Ebene über den C-Dateideskriptoren auf niedriger Ebene.
Für die meisten Dateiobjekte, die du in Python über die integrierte Funktion open() erzeugst, kennzeichnet f.close() das Python-Dateiobjekt aus Sicht von Python als geschlossen und sorgt außerdem dafür, dass der darunter liegende C-Dateideskriptor geschlossen wird. Das passiert auch automatisch im Destruktor von f, wenn f zu Müll wird.
Aber stdin, stdout und stderr werden von Python besonders behandelt, weil C ihnen ebenfalls einen besonderen Status gibt. sys.stdout.close() auszuführen kennzeichnet das Dateiobjekt auf Python-Ebene als geschlossen, schließt den zugehörigen C-Dateideskriptor aber nicht.
Um den darunter liegenden C-Dateideskriptor für einen dieser drei zu schließen, solltest du zuerst sicher sein, dass du das wirklich willst — du bringst damit zum Beispiel vielleicht Erweiterungsmodule in Schwierigkeiten, die Ein- und Ausgabe machen wollen. Wenn ja, verwende os.close():
os.close(stdin.fileno())
os.close(stdout.fileno())
os.close(stderr.fileno())
Oder du verwendest die Zahlenkonstanten 0, 1 und 2.
Netzwerk- und Internetprogrammierung¶
Welche WWW-Werkzeuge gibt es für Python?¶
Siehe die Kapitel Internetprotokolle und Unterstützung dafür und Verarbeitung von Internetdaten im Referenzhandbuch der Bibliothek. Python hat viele Module, die dir beim Bau von Websystemen auf Server- und auf Clientseite helfen.
Eine Übersicht der verfügbaren Frameworks pflegt Paul Boddie unter https://wiki.python.org/moin/WebProgramming.
Welches Modul sollte ich zur Hilfe beim Erzeugen von HTML verwenden?¶
Eine Sammlung nützlicher Links findest du auf der Wiki-Seite Web Programming.
Wie versende ich aus einem Python-Skript E-Mail?¶
Verwende das Modul smtplib aus der Standardbibliothek.
Hier ein sehr einfacher interaktiver Mailversender, der es verwendet. Diese Methode funktioniert auf jedem Rechner, der einen SMTP-Dienst unterstützt.
import sys, smtplib
fromaddr = input("From: ")
toaddrs = input("To: ").split(',')
print("Enter message, end with ^D:")
msg = ''
while True:
line = sys.stdin.readline()
if not line:
break
msg += line
# der eigentliche Mailversand
server = smtplib.SMTP('localhost')
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
Eine Alternative nur für Unix verwendet sendmail. Der Ort des Programms sendmail unterscheidet sich je nach System, manchmal ist es /usr/lib/sendmail, manchmal /usr/sbin/sendmail. Die Manpage von sendmail hilft dir weiter. Hier etwas Beispielcode:
import os
SENDMAIL = "/usr/sbin/sendmail" # Ort von sendmail
p = os.popen("%s -t -i" % SENDMAIL, "w")
p.write("To: receiver@example.com\n")
p.write("Subject: test\n")
p.write("\n") # Leerzeile, die Kopfzeilen vom Rumpf trennt
p.write("Some text\n")
p.write("some more text\n")
sts = p.close()
if sts != 0:
print("Sendmail exit status", sts)
Wie vermeide ich Blockieren in der Methode connect() eines Sockets?¶
Das Modul select wird häufig verwendet, um bei asynchroner Ein- und Ausgabe auf Sockets zu helfen.
Damit das TCP-connect nicht blockiert, kannst du den Socket in den nicht blockierenden Modus setzen. Beim connect() verbindest du dich dann entweder sofort (unwahrscheinlich) oder bekommst eine Ausnahme, die die Fehlernummer als .errno enthält. errno.EINPROGRESS zeigt an, dass die Verbindung im Aufbau, aber noch nicht fertig ist. Verschiedene Betriebssysteme geben verschiedene Werte zurück, du musst also prüfen, was auf deinem System zurückkommt.
Mit der Methode connect_ex() kannst du vermeiden, dass eine Ausnahme entsteht. Sie gibt einfach den errno-Wert zurück. Zum Abfragen kannst du connect_ex() später erneut aufrufen – 0 oder errno.EISCONN zeigen an, dass du verbunden bist – oder du übergibst diesen Socket an select.select(), um zu prüfen, ob er beschreibbar ist.
Datenbanken¶
Gibt es in Python Schnittstellen zu Datenbankpaketen?¶
Ja.
Schnittstellen zu plattenbasierten Hashes wie DBM und GDBM sind ebenfalls im Standard-Python enthalten. Es gibt außerdem das Modul sqlite3, das eine leichtgewichtige, plattenbasierte relationale Datenbank bereitstellt.
Unterstützung für die meisten relationalen Datenbanken ist verfügbar. Einzelheiten stehen auf der Wiki-Seite DatabaseProgramming.
Wie setzt man in Python persistente Objekte um?¶
Das Bibliotheksmodul pickle löst das auf sehr allgemeine Weise, auch wenn du Dinge wie offene Dateien, Sockets oder Fenster weiterhin nicht speichern kannst, und das Bibliotheksmodul shelve verwendet pickle und (g)dbm, um persistente Mappings zu erzeugen, die beliebige Python-Objekte enthalten.
Mathematik und Numerik¶
Wie erzeuge ich in Python Zufallszahlen?¶
Das Standardmodul random setzt einen Zufallszahlengenerator um. Die Verwendung ist einfach:
import random
random.random()
Das gibt eine zufällige Gleitkommazahl im Bereich [0, 1) zurück.
In diesem Modul gibt es auch viele weitere spezialisierte Generatoren, zum Beispiel:
randrange(a, b)wählt eine ganze Zahl im Bereich [a, b).uniform(a, b)wählt eine Gleitkommazahl im Bereich [a, b).normalvariate(mean, sdev)zieht aus der Normalverteilung, also der Gauß-Verteilung.
Einige Funktionen auf höherer Ebene arbeiten direkt auf Sequenzen, zum Beispiel:
choice(S)wählt ein zufälliges Element aus einer gegebenen Sequenz.shuffle(L)mischt eine Liste an ihrem Platz, permutiert sie also zufällig.
Es gibt außerdem eine Klasse Random, die du instanziieren kannst, um mehrere voneinander unabhängige Zufallszahlengeneratoren zu erzeugen.