Die Entwickler haben Python 3.4 an zahlreichen Ecken optimiert und die Standardbibliothek um einige interessante Module erweitert, findet Python-Experte Mike Müller.
Einige Dinge verändert auch Python 3.4 nicht: Die neueste Version der 23 Jahre alten Programmiersprache behält die Syntax bei, weshalb Python-3.3-Programme weiterhin unverändert funktionieren. Einige alte Zöpfe schneiden die Entwickler dennoch ab: Python 3.4 unterstützt die Betriebssysteme Vax/VMS, OS/2 und Windows 2000 nicht mehr. Nutzer dieser Systeme müssen daher auf Python 3.3 ausweichen.
Ansonsten ist alles wie gehabt: Die so genannten Python Enhancement Proposals, kurz PEP [1], fassen die Details für viele der neuen Merkmale zusammen. Die Lektüre lohnt sich, weil die PEPs neben Hintergrundinformationen auch Beispiele für den praktischen Einsatz liefern.
Mit pip von Anfang an
Python bietet laut dem Python Package Index [2] derzeit über 42 000 Pakete an. Mit »pip« [3] lassen sich diese, inklusive ihrer Abhängigkeiten, sehr komfortabel installieren. Haben viele Nutzer bislang nach der Installation von Python zunächst »pip« heruntergeladen, ist das nun nicht mehr nötig: Die neueste Python-Version bringt »pip« standardmäßig mit. Spielt es dann noch mit »pyenv« zusammen, wird die Arbeit mit einer Python-Standardinstallation für den Entwickler wesentlich angenehmer. Das bei Python 3 schon länger zur Standardbibliothek gehörende »pyenv« erlaubt die Arbeit mit virtuellen, voneinander isolierten Python-Umgebungen.
Asynchrone Programmierung
Python-Schöpfer Guido van Rossum höchstpersönlich ist der Autor des »asyncio« -Moduls. Vor dessen Programmierung hat er ausgiebige Gespräche mit den Entwicklern ähnlicher Python-Bibliotheken wie Twisted, Tornado, Zero MQ und Pyftpdlib geführt. Wollen Entwickler die Event-Loop in andere Systeme einbauen, kann »asyncio« als Grundlage für diese Bibliotheken dienen. Weiterhin bietet »asyncio« auf höherem Abstraktionsniveau einen Scheduler auf Basis von »yield from« an. In dem recht umfangreichen PEP 3156 [4] beschreibt van Rossum das Modul detailliert. Das API ist dabei noch vorläufig, und Änderungen in Python 3.5 sind möglich.
Aufzählungen mit Enum
Nach mehreren Anläufen hat Python nun auch einen Aufzählungstyp im Gepäck. Die Klasse »Enum« aus dem gleichnamigen Modul weist eindeutigen, konstanten Werten symbolische Namen zu [5]. So ordnen Entwickler die Zahlen 0 bis 6 den Wochentagen zu oder beschreiben Schulnoten mit »1« für »sehr gut« und »2« für »gut« . Die Attribute einer Klasse, die von »Enum« erbt, übernehmen die Rolle der symbolischen Namen.
Zur Python-Philosophie gehört, dass es immer einen bevorzugten Weg geben soll, um ein Problem zu lösen [6]. Dank des neuen und im Vorfeld viel diskutierten Aufzählungstyps lassen sich bestimmte Aufgaben nun endlich auf einem standardisierten Weg lösen, selbst gestrickte Ansätze sind nicht mehr nötig.
Besser als Objekte
Es hat sich in der Praxis bewährt, für den Umgang mit C-Bibliotheken nicht nur einfache Schnittstellen, sondern zusätzliche, leistungsfähigere Module anzubieten, um die Vorteile von Python besser zu nutzen. Ein gutes Beispiel dafür liefert das viel genutzte »datetime« -Modul. Im Vergleich zum »time« -Modul, das einfach die Funktionalität des C-API nachbaut, erlauben die »datetime« -Objekte komfortable Berechnungen. Sie befreien den Programmierer zum Beispiel davon, komplizierte Regeln selbst zu implementieren, um Schaltjahre zu berechnen.
Das Prinzip lässt sich auch auf Pfade des Dateisystems ausweiten. Während das altgediente »os.path« Dateipfade stets als Strings behandelt, eröffnet das neue Modul »pathlib« (Abbildung 1) einen objektorientierten Zugang zum Dateisystem. Doch es gibt weitere Implementierungen mit dem gleichen Ziel, wie etwa »py.path« [7] oder die etwas spezialisierte Klasse »FilePath« in Twisted [8].
Die »pathlib« -Bibliothek unterscheidet zwischen reinen (Pure Path) und konkreten Pfaden (Concrete Path) sowie zwischen Pfaden für Windows und Posix, wozu Linux, Unix, BSD, OS X und so weiter zählen. Reine Pfade erlauben das Arbeiten mit Pfadnamen. Listing 1 zeigt Beispiele. Konkrete Pfade greifen im Gegensatz zu den reinen auf das Dateisystem zu und geben Auskunft über den Pfad (Listing 2).
Listing 1
Reine Pfade
01 >>> from pathlib import Path
02 >>> p = Path('
/Users/mike/tmp/beispiel.py
')
03 >>> p.name
04 'beispiel.py'
05 >>> p.suffix
06 '.py'
07 >>> p.root
08 '/'
09 >>> p.parts
10 ('/', '
Users
', '
mike
', '
tmp
', '
beispiel.py
')
Listing 2
Konkrete Pfade
01 >>> p.is_file()
02 True
03
04 >>> p.is_dir()
05 False
06
07 >>> p.stat()
08 os.stat_result(st_mode=33188, st_ino=49878510, st_dev=234881026, st_nlink=1, st_uid=501, st_gid=20, st_size=20, st_atime=1396777942, st_mtime=1396777942, st_ctime=1396777942)
09
10 >>> Path.cwd()
11 PosixPath('
/Users/mike
')
»PurePosixPath« oder »PureWindowsPath« ermöglichen es dabei, reine Pfade auf einer anderen Plattform als der aktuellen zu bearbeiten, also Windows-Pfade auf Posix-Systemen und umgekehrt. In den meisten Fällen reicht es jedoch aus, direkt mit »Path« zu arbeiten. Auch das API von »pathlib« befindet sich noch im Übergang und könnte sich in Python 3.5 ändern.
Statistik an Bord
Trotz Pythons Motto “Batteries included” gab es bisher kein Modul mit einfachen statistischen Funktionen in der Standardbibliothek. Numpy und Scipy bieten ausgereifte statistische Bibliotheken mit vielen Verteilungsfunktionen für professionelle Anwender. Nicht-wissenschaftliche Nutzer dieser Pakete mussten diese aber stets aufwändig installieren und sich einarbeiten, selbst wenn sie nicht regelmäßig damit gearbeitet haben. Natürlich lassen sich der Mittelwert und die Standardabweichung leicht selbst berechnen, doch bereitet hier die numerische Genauigkeit schnell Probleme. Die Berechnung des Mittelwertes mit dieser Funktion:
>>> def mean(data): ... return sum(data)/len(data)
klappt nur für kleine Zahlen:
>>> mean([1, 5, 8, 1, -1]) 2.8
scheitert aber im Umgang mit sehr großen und sehr kleinen Zahlen:
>>> mean([1, 5, 8, 1e20, -1e20]) 0.0
Das Problem liegt in der Abbildung von »float« -Zahlen. Mit dem neuen »statistics« -Modul [9] funktioniert das besser:
>>> import statistics >>> statistics.mean([1, 5, 8, 1e20, -1e20]) 2.8
Keine Frage: Die neue Statistikfunktion vereinfacht Python-Nutzern das Leben.
Flexible Datentypen
Viele in die Standardbibliothek eingebaute Funktionen wie »len()« , »iter()« , »pprint.pprint()« oder »copy.copy()« verhalten sich je nach Datentyp, den sie übergeben bekommen, unterschiedlich. Für selbst verfasste Funktionen gab es bislang keinen standardisierten Weg, um diesen unterschiedliche Reaktionen auf Datentypen zu entlocken. Die Single-Dispatch Generic Functions [10] erlauben es, eine Funktion abhängig vom Datentyp des ersten übergebenen Arguments je etwas anders tun zu lassen (Listing 3).
Listing 3
Single-Dispatch Generic Functions
01 >>> from functools import singledispatch
02 >>> @singledispatch
03 ... def func(arg1, arg2):
04 ... print('kein Dispatch')
05
06 >>> @func.register(int)
07 ... def _(arg1, arg2):
08 ... print('int')
09
10 >>> @func.register(str)
11 ... def _(arg1, arg2):
12 ... print('str')
13
14 # erstes Argument ist eine Ganzzahl
15 >>> func(1, 'egal')
16 int
17
18 # erstes Argument ist eine Zeichenkette
19 >>> func('abc', 'egal')
20 str
21
22 # erstes Argument löst kein Dispatch aus, da Typ nicht registriert
23 >>> func([1, 2, 3], 'egal')
24 kein Dispatch
Mehr Sicherheit
Im Vergleich zu anderen Softwaresystemen ist die Fehlerrate im Python-Code sehr gering [11], trotzdem sichern die Entwickler die Sprache gegen Angriffe ab. Der Hash-Algorithmus für die in Python allgegenwärtigen Dictionaries ist in der neuen Version resistent gegen DoS-Attacken mit speziell dafür präparierten Schlüsseln und lässt sich zudem leicht gegen eigene Implementierungen austauschen. Das SSL-Modul unterstützt neben weiteren Verbesserungen TLSv1.1 und TLSv1.2. Weil die Kindprozesse weniger Daten bekommen, lässt sich das Modul »multiprocessing« nun auch auf Unix- und Windows-Systemen sicherer einsetzen.
Interna
Python 3.4 lädt Programmierer ein, eigene Memory-Allokatoren einzusetzen. Das ist besonders für eingebettete Interpreter mit wenig Ressourcen und zum Debuggen vorteilhaft. Gab es bislang immer wieder Probleme am Programmende, wenn »__del__« -Methoden im Einsatz waren, soll der neue Finalisierungsmechanismus nun Abhilfe schaffen. Über das Modul »tracemalloc« erhält der Entwickler einen Überblick über den genutzten Speicher und spürt Speicherprobleme auf.
Weiter ohne GIL
Neben den genannten warten noch zahlreiche weitere Neuerungen [12] auf den Python-Entwickler wie etwa ein neues »pickle« -Protokoll und Verbesserungen am »marshal« -Format, neue Möglichkeiten für den Import von Modulen oder bessere Inspektionsmöglichkeiten. Zudem machen einige Verbesserungen Python schneller.
Ein großer Wunsch der Entwickler wird sich aber wohl auch in der absehbaren Zukunft nicht erfüllen: ein Python ohne das Global Interpreter Lock (GIL). Allerdings gibt es neben dem »multiprocessing« -Modul weitere externe Module und Projekte, die den Einsatz mehrerer CPUs für bestimmte Zwecke erlauben. Software Transactional Memory (STM) mit Pypy funktioniert im Prinzip [13], und es gibt einige Projekte, die mit LLVM als Zielplattform arbeiten, wie zum Beispiel [14] und [15].
Doch auch wenn die Entwickler nicht sämtliche Wünsche erfüllen, bringt Python 3.4 nützliche Neuerungen mit und macht die Programmiersprache besser nutzbar. Einmal mehr ist es gelungen, Neulingen den Einstieg zu vereinfachen und zugleich den fortgeschrittenen Anwendern anspruchsvolle Werkzeuge an die Hand zu geben. Ein Umstieg von Python 2.x auf Python 3 erscheint dadurch noch lohnender. (kki)
Infos
- Python Enhancement Proposal: http://legacy.python.org/dev/peps/pep-0001/
- Der Python Package Index: https://pypi.python.org/pypi
- Pip-Bootstrapping im PEP 453: http://legacy.python.org/dev/peps/pep-0453/
- Details zu »asyncio« in PEP 3156: http://legacy.python.org/dev/peps/pep-3156/
- PEP zu »Enum« : http://legacy.python.org/dev/peps/pep-0435/
- Eingabe von »import this« am Python-Prompt, das klappt auch direkt im Web: https://www.python.org
- Das »py.path« -Interface: http://pylib.readthedocs.org/en/latest/path.html
- »FilePath« in Twisted: http://twistedmatrix.com/documents/current/api/twisted.python.filepath.FilePath.html
- Statistik-Modul: http://legacy.python.org/dev/peps/pep-0450/
- Details zu »pathlib« in PEP 428: http://legacy.python.org/dev/peps/pep-0428/
- Python hat kaum Bugs: https://www.linux-magazin.de/NEWS/Coverity-Python-haelt-exzellente-Code-Qualitaet/
- Release Notes zu Python 3.4: https://www.python.org/download/releases/3.4.0/
- STM in Pypy: http://morepypy.blogspot.de/search/label/stm
- Numba: http://numba.pydata.org
- Pyston: https://github.com/dropbox/pyston







