Free-threaded Python – Top oder Flop?

Veit Schiele

5. September 2025

6–7 Minuten

../_images/seams.jpg

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:

Dies hat mit einigen bekannten Problemen von asyncio zu tun:

  • asyncio unterstützt keine asynchronen Operationen auf dem Dateisystem. Selbst wenn Dateien mit O_NONBLOCK geöffnet werden, werden Lese- und Schreibvorgänge blockiert. Eine Lösung hierfür besteht darin, das Paket aiofiles 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 oder httpx 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.