Free-threaded Python – hit or miss?

Veit Schiele

5 September 2025

5–6 minutes

../_images/seams.jpg

Python 3.14 will be released in a few weeks with some important changes regarding concurrency:

Both features represent advances in the use of Python for concurrent and parallel code execution. But are they threatened with a marginal existence similar to asyncio?

Why did asyncio fail?

The typical use case for asyncio is web development. Coroutines are well suited for process-independent network calls such as HTTP requests and database queries. Why should the entire Python interpreter be blocked while waiting for a query to be executed on another server? And yet, popular frameworks still do not support asyncio:

This has to do with some known issues with asyncio:

  • asyncio does not support asynchronous operations on the file system. Even if files are opened with O_NONBLOCK, read and write operations are blocked. One solution to this is to use the aiofiles package, which provides asynchronous file functions.

  • asyncio is not intuitive. For example, what does it mean when code is ‘blocked’, and when is it necessary to switch to threads? Without this basic knowledge, asynchronous code will behave incorrectly, but will not break. Developers therefore do not get the quick feedback they expect from Python.

    ‘An event loop runs in a thread (typically the main thread) and executes all callbacks and Tasks in its thread. While a Task is running in the event loop, no other Tasks can run in the same thread. When a Task executes an await expression, the running Task gets suspended, and the event loop executes the next Task.’

    Source: Concurrency and Multithreading

  • Supporting both synchronous and asynchronous APIs is challenging. The backend may need to be fragmented for synchronous and asynchronous operations. For asynchronous operations, aiohttp or httpx can be used for this purpose.

  • Finally, testing your asynchronous code also requires various mocks, various calls and, in the case of pytest, a whole range of extensions and patterns for fixtures. This can quickly become confusing.

    See also

    async test patterns for Pytest by Anthony Shaw

So it’s not surprising that asyncio can’t even hold its own for asynchronous network access. Instead, the Python web framework FastAPI has become very popular for this purpose, using an alternative implementation of the event loop called uvloop.

The use cases for asyncio will therefore remain minimal and its distribution very limited.

Does free-threaded Python make it better?

Python 3.13 introduced a ‘free-threaded’ version of Python, in which the GIL was removed and replaced with smaller, more granular locks. However, the 3.13 version proved to be insufficiently stable for productive use. This looks better in Python 3.14. In Python 3.14t, the InterpreterPoolExecutor and free-threading features will make more parallel and concurrent use cases feasible and faster. In the following example, up to eight CPUs can be used simultaneously with the multithreaded argument:

$ 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

Free-threaded Python also eliminates many of the problems with asyncio that I discussed in this article. In addition, a number of Python libraries now support free-threaded Python, including:

Library

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 we will now try out free-threaded Python in some of our well-tested projects.