Inhaltsverzeichnis
Python
Python ist eine interpretierte höhere Programmiersprache, die häufig als Skriptsprache eingesetzt wird. Die Version Python 2 wird seit April 2020 nicht mehr unterstützt.
Übersicht über nützliche Bibliotheken
Name | Einsatzzweck |
---|---|
configobj | Parsen von Konfigurationsdateien |
argparse | Parsen von Kommandozeilenoptionen, auch zum Parsen von Konfigurationsdateien, configobj ist dabei jedoch komfortabler |
matplotlib | Erzeugen von Plots |
pandas | Datenanalyse |
Standard-Library
Switch-Case
Python kennt keine Switch-Case-Anweisung. Die Funktion kann mit If-Else-Anweisung nachgebildet werden, es gibt aber auch weitere Möglichkeiten.
For-Schleifen
In der normalen For-Schleife mit range müssen die Argumente Integers sein:
for i in range(start, stop, step):
Sind sie Floats kann arange aus numpy verwendet werden:
for i in numpy.arange(start, stop, step):
Für eine feste Anzahl von Schritten, kann linspace verwendet werden:
for i in numpy.linspace(start, stop, nrSteps):
Wird der Index einer For-Schleife benötigt, kann enumerate
verwendet werden:
ints = [8, 23, 45, 12, 78] for idx, val in enumerate(ints): print idx, val
String-Formatting
Python unterstützt zwei verschiedene Möglichkeiten zur Stringinterpolation: den %
-Operator und .format()
. Letzteres ist die neuere und empfohlene Variante.
Beispiel:
#alt '%s %s' % ('eins', 'zwei') #neu '{} {}'.format('eins', 'zwei')
- pyformat.info viele Beispiele mit Gegenüberstellung von alter und neuer Variante
Bools ausgeben
Um boolsche Werte in anderen textueller Darstellung als True
/False
auszugeben kann man diesen Trick verwenden:
print "state: {0}".format(['Off','On'][state])
Modul neu laden
Um ein bereits importiertes Modul neu zu laden (z.B. um globale Variablen zurück zu setzen), muss ein reload
durchgeführt werden.
Je nach Python-Version liegt diese Funktion in einem anderen Modul:
Python-Version | Befehl |
---|---|
2 | reload(module) |
3-3.3 | import imp imp.reload(module) |
>3.4 | import importlib importlib.reload(module) |
Buffering
Standardmäßig ist die Ausgabe von Python gebuffert.
Das kann insbesondere bei der Verwendung von Umleitungen command > out.txt
oder dem Einsatz von tee
(command | tee out.txt
) und langen Skriptlaufzeiten störend sein.
Folgende Möglichkeiten existieren zur Lösung:
- Mit
sys.stdout.flush()
explizit einen Flush des Buffers anfordern - Das Skript mit
python -u
aufrufen (geht auch in Shebang-Zeile). Damit sind alle Ausgaben ungebuffert. - Seit Python 3.3 kennt
print
den Parameterflush
:print('Test', flush=True)
- Vor dem ersten
print
-Befehl folgendes aufrufen:sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Damit sind alle Ausgaben ungebuffert.
mehrfache Einträge aus Liste entfernen
Mehrfache Einträge aus Listen lassen sich durch die Umwandlung in ein Set (und eine Rückumwandlung in eine Liste) entfernen:
unique_list = list(set(nonunique_list))
Die Einträge sind dann ungeordnet.
String zu Liste konvertieren
Soll ein String zu einer Liste mit einem Element umgewandelt werden, können eckige Klammern []
verwendet werden:
test_string = "abc" text_list = [test_string] #text_list = ["abc"]
Der Befehl list
erzeugt dagegen eine Liste bestehend aus den einzelnen Zeichen des Strings:
test_string = "abc" text_list = list(test_string) #text_list = ['a', 'b', 'c']
NaN erzeugen
Ein NaN (Not a Number) kann mit float('NaN')
erzeugt werden.
Seit Python 3.5 kann auch math.nan
verwendet werden.
Exceptions
argparse
Matplotlib
lmodern mit T1-Encoding
Um mit matplotlib PDF-Dateien mit der Schriftart lmodern und korrektem T1-Encoding zu erstellen (zum Beispiel für richtig kopierbare Umlaute) muss LaTeX anstelle des internen Mechanismus von matplotlib verwendet werden. Dazu sind folgende Einstellung notwendig:
plt.rcParams['text.latex.preamble']=[r"\usepackage{lmodern} \usepackage[T1]{fontenc}"] params = { 'text.usetex' : True, 'text.latex.unicode': True, 'font.family' : "lmodern" } plt.rcParams.update(params)
Das Setzen von \usepackage{lmodern}
vor den anderen Optionen ist notwendig, siehe http://stackoverflow.com/a/18633695
Der Textsatz mit LaTeX ist deutlich langsamer als der interne Mechanismus von matplotlib.
LaTeX wird nicht im aktuellen Arbeitsverzeichnis ausgeführt, sondern im Cache-Verzeichnis (~/.cache/matplotlib
unter Linux oder über get_cachedir()
herausfinden).
Deshalb funktioniert \input
mit relativen Pfaden nicht.
Die TeX-Dateien verbleiben im Cache-Verzeichnis und können zum Debugging nützlich sein.
"Unknown Font" in Python 3
Wird eine Grafik mit matplotlib unter Python 3 als PDF exportiert, werden die Fonts im PDF mit pdffonts
oder PDF-Viewern wie Okular u.U. als „unknown font“ angezeigt.
Dabei handelt es sich um diesen Bug.
Abhilfe:
- Python 2 verwenden oder
- eine aktuelle matplotlib-Version verwenden
Achsenbeschriftung in wissenschaftlicher Schreibweise
Mit der Funktion ticklabel_format kann die Achsenbeschriftung in wissenschaftlicher Schreibweise gesetzt werden.
mpl.ticklabel_format(style='sci', scilimits=(-3,4), axis='both')
Die Defaultwerte für scilimits
werden in rcParams
durch axes.formatter.limits
gesetzt.
Nur Ganzzahlen als Achsenbeschriftung
Der einfachste Weg nur Ganzzahlen als „Ticks“ auf den Achsen anzuzeigen, ist dieser:
from matplotlib.ticker import MaxNLocator ax = plt.figure().gca() ax.yaxis.set_major_locator(MaxNLocator(integer=True))
Ränder beim Autoscaling
Um zu verhindern, dass die Datenpunkte nicht mehr auf den Achsen liegen und daher schlecht zu erkennen sind, gibt es zwei Möglichkeiten. Entweder kann in der matplotlibrc
folgendes gesetzt werden:
axes.xmargin : 0.1 axes.ymargin : 0.1
Dies wirkt dann für alle Plots. Um jeden Plot individuell zu ändern:
plt.plot(t,np.sin(t)) plt.margins(x=0.1, y=0.1)
Der angegebene Werte kann jeweils zwischen 0 und 1 liegen.
Innerhalb von Subplots müssen die Ränder für jede Achse separat gesetzt werden, plt.margins()
wirkt nur auf die letzte:
for ax in axes: ax.margins(x=0.1, y=0.1)
Links
Configobj
configobj ist eine Klasse mit der Konfigurationsdateien einfach geparst und die geparsten Werte valididert werden können.
Validierung der Argumente
Mit dem validator
-Objekt können die Argumente gegen eine Spezifikation („configspec“) geprüft und in den entsprechenden Typ umgewandelt werden, hier eine Liste der möglichen Argumenttypen.
Die in der configspec angegebenen Typen werden nicht geprüft.
Tippfehler (z.B. bool
vs. boolean
) werden daher nicht erkannt und der Typ des Arguments bleibt unverändert.
Validierung von Listen mit nur einem Argument
Gibt man in der configspec zur Validierung string_list
an und enthält die zugewiesene Liste nur ein Element, wird der String in eine Liste von Buchstaben zerlegt.
Benötigt man eine Liste mit einem Element muss die Zuweisung mit einem Komma am Ende erfolgen:
testvar = "teststring",
Alternative kann die configspec auf force_list
geändert werden.
Dabei wird allerdings keine Typprüfung vorgenommen.
Schriftgröße der Legende
Die einfachste Art die Schriftgröße der Legende zu verändern ist diese:
plot.legend(prop={'size':6})
Tick-Frequenz ändern
Um den Abstand der Ticks manuell zu setzen, kann der MultipleLocator
verwendet werden.
Als Argument bekommt er den Abstand der Ticks.
import matplotlib.ticker as ticker ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
Links
csv
Zeilenende
Standardmäßig wird beim Schreiben das Windowszeilenende \r\n
benutzt.
Um dies zu ändern, kann der lineterminator
explizit gesetzt werden:
writer = csv.writer(f, lineterminator='\n')
setuptools
Vergleichen von Versionsnummern
Mit der Funktion parse_version
lassen sich komfortabel auch komplizierte Versionsnummern vergleichen:
from pkg_resources import parse_version if parse_version('2.1-rc2') < parse_version('2.1'): print "Version is to low!"
Die Version von Python-Modulen lässt sich über die __version__-Eigenschaft herausfinden:
import scipy print scipy.__version__
numpy
alle Inf in Array durch Null ersetzen
Alle INFs in einem Numpy-Array lassen sich wie folgt durch Null oder einen beliebigen anderen Wert ersetzen:
from numpy import inf x = numpy.array([-inf, -inf, 37.49668579]) x[x == inf] = 0
UTF-8
Python 3 unterstützt UTF-8 gut und komfortabel. In Python 2 muss das Encoding eines Sourcefiles mit
# -*- coding: utf-8 -*-
oder
# coding: utf8
explizit gesetzt werden und Strings müssen das Präfix
u
bekommen:
some_string = u'ÜÖÄ'
Tipps & Tricks
Prüfen, ob String numerisch
Um zu prüfen, ob ein String numerisch ist, ist es häufig nicht sinnvoll, die Funktionen isdigit()
oder isnumeric()
(nur für Unicodestrings definiert) zu verwenden, da diese keine negativen Zahlen akzeptieren.
Als Alternative kann man sowas verwenden:
def isnumeric(value) try: val = float(value) return True except ValueError: return False
Links
- Python 3 Patterns, Recipes and Idioms noch unfertiges Open-Source-Buch