Free-threaded Python – Top oder Flop?¶

Python 3.14 kommt in wenigen Wochen mit einigen wichtigen Änderungen in Bezug auf auf Parallelität:
Beide Features stellen Fortschritte in der Verwendung von Python zur gleichzeitigen und parallelen Ausführung von Code dar. Aber droht ihnen eine ähnliche Randexistenz wie asyncio?
Warum floppte asyncio
?¶
Der typische Anwendungsfall für asyncio
ist die Webentwicklung. Coroutinen
eignen sich gut für prozessunabhängige Netzwerkaufrufe wie HTTP-Requests und
Datenbankabfragen. Warum sollte der gesamte Python-Interpreter blockiert werden,
während darauf gewartet wird, dass eine Abfrage auf einem anderen Server
ausgeführt wird? Und dennoch unterstützen beliebte Frameworks noch immer nicht
asyncio
:
Django unterstützt nur teilweise
asyncio
; so wird beim ORM „noch an der Unterstützung von async“ gearbeitet.Die
asyncio
-Unterstützung von Flask ist wenig leistungsfähig, siehe Using async and await.SQLAlchemy hat erst 2023
asyncio
-Unterstützung erhalten, siehe What’s New in SQLAlchemy 1.4?Im Python für Data Science-Tutorial wird
asyncio
nur als letztes Mittel zur Performance-Optimierung empfohlen.Siehe auch
Dies hat mit einigen bekannten Problemen von asyncio
zu tun:
asyncio
unterstützt keine asynchronen Operationen auf dem Dateisystem. Selbst wenn Dateien mitO_NONBLOCK
geöffnet werden, werden Lese- und Schreibvorgänge blockiert. Eine Lösung hierfür besteht darin, das Paketaiofiles
zu verwenden, das euch asynchrone Datei-Funktionen bietet.asyncio
ist nicht intuitiv. Was bedeutet es beispielsweise, wenn Code „blockiert“ wird, und wann ist es notwendig, auf Threads auszuweichen? Ohne diese Grundlagenkenntnisse wird asynchroner Code Fehlverhalten zeigen, aber an sich nicht kaputtgehen. Developer erhalten also nicht das schnelle Feedback, das sie von Python erwarten.„Eine Event Loop läuft in einem Thread (normalerweise dem Haupt-Thread) und führt alle Callbacks und Tasks in diesem Thread aus. Während ein Task in der Event Loop läuft, können keine anderen Tasks im selben Thread ausgeführt werden. Wenn ein Task einen await-Ausdruck ausführt, wird der laufende Task angehalten und die Event Loop führt den nächsten Task aus.“
Quelle: Concurrency and Multithreading
Die Unterstützung sowohl synchroner als auch asynchroner APIs ist herausfordernd. Ggf. muss das Backend für synchrone und asynchrone Vorgänge fragmentiert werden. Für asynchrone Vorgänge können hierfür
aiohttp
oderhttpx
verwendet werden.Schließlich erfordert auch das Testen eures asynchronen Codes verschiedene Mocks, verschiedene Aufrufe und im Fall von pytest eine ganze Reihe von Erweiterungen und Mustern für Fixtures. Dies kann sehr schnell verwirrend werden.
Siehe auch
Anthony Shaw: async test patterns for Pytest
So ist es also nicht verwunderlich, dass sich noch nicht einmal für asynchrone
Netzwerk-Zugriffe asyncio
behaupten kann. Stattdessen wurde hierfür das
Python-Web-Framework
FastAPI sehr populär, das
eine alternativen Implementierung des Event Loop verwendet, nämlich uvloop.
Die Anwendungsfälle für asyncio
werden also weiterhin minimal und die
Verbreitung daher sehr eingeschränkt bleiben.
Macht es Free-Threaded Python besser?¶
Python 3.13 führte eine „Free-Threaded”-Version von Python ein, bei der das
GIL entfernt und durch kleinere, granularere
Sperren ersetzt wurde. Die 3.13-Version erwies sich jedoch für den produktiven
Einsatz nicht stabil genug. In Python 3.14 scheint dies besser auszusehen. In
Python 3.14t werden die InterpreterPoolExecutor- und
Free-Threading-Funktionen mehr
parallele und gleichzeitige Anwendungsfälle praktikabel und schneller machen. Im
folgenden Beispiel dürfen mit dem multithreaded
-Argument bis zu acht CPUs
gleichzeitig verwendet werden:
$ uv run python -X gil=1 parse.py
Using single thread for parsing news
Parsing speed: 15 news/sec
$ uv run python -X gil=1 parse.py --multithreaded
Using multithreading for parsing news
Parsing speed: 37 news/sec
$ uv run python -X gil=0 parse.py --multithreaded
Using multithreading for parsing news
Parsing speed: 73 news/sec
Mit Free-Threaded Python verschwinden auch viele der Probleme von asyncio
,
die ich in diesem Beitrag angesprochen habe. Zudem unterstützen mittlerweile
auch etliche Python-Bibliotheken free-threaded Python, u.a.:
Bibliothek |
Version |
---|---|
argon2-cffi-bindings |
≥ 25.1.0 |
CFFI |
≥ 2.0.0 |
cibuildwheel |
≥ 2.19 |
Cython |
≥ 3.1.0 |
hypothesis |
≥ 6.135.32 |
joblib |
≥ 1.4.2 |
matplotlib |
≥ 3.9.0 |
maturin |
≥ 1.7.5 |
meson-python |
≥ 0.16.0 |
NumPy |
≥ 2.1.0 |
pandas |
≥ 2.2.3 |
Pillow |
≥ 11.0.0 |
pydantic |
≥ 2.11.0 |
pybind11 |
≥ 2.13 |
PyO3 |
≥ 0.23 |
PyTorch |
≥ 2.6.0 |
scikit-learn |
≥ 1.6.0 |
SciPy |
≥ 1.15.0 |
Shapely |
≥ 2.1.0 |
tox |
≥ 4.26.0 |
uv |
≥ 0.4.24 |
So werden wir nun Free-Threaded Python in einigen unserer gut getesteten Projekten ausprobieren.