The first two posts in this series covered new directives in mod_wsgi 6.0.0 that change the concurrency model the interpreter runs under. WSGIPerInterpreterGIL opts a sub-interpreter into its own GIL. WSGIFreeThreading opts a process into PEP 703 free-threaded mode. This third directive, WSGISwitchInterval , is a different sort of thing. It does not change the concurrency model. It exposes a…
The previous post in this series walked through tuning WSGISwitchInterval to claw back throughput on a multi-threaded mod_wsgi daemon group whose workload is CPU-bound Python. Tightening the switch interval recovered most of the throughput a two-process, five-thread shape had lost compared with the ten-process, one-thread baseline. What it did not change was per-process CPU usage. Each process…
mod_wsgi 6.0.0 is currently available as a release candidate. You can install it from PyPI, or grab the source from the GitHub releases page. There is a significant amount of code cleanup behind this release, alongside a range of new features and operator-facing improvements that have been overdue for some time. Rather than describe everything in one post, I am going to work through the headline…
The previous post in this series covered the new WSGIPerInterpreterGIL directive in mod_wsgi 6.0.0 and the PEP 684 per-interpreter GIL feature that landed in Python 3.12. This post is about its sibling, WSGIFreeThreading , which targets PEP 703 free-threaded Python builds. The two directives sit next to each other in the mod_wsgi configuration vocabulary and they both opt processes into a…
Continuing the tour through the wrapt 2.2.0 release, the last piece worth a closer look is the new async support in wrapt.synchronized . The decorator has been part of wrapt from the start, but until 2.2.0 it only really did the right thing for synchronous code. Applying it to an async def function used to give the appearance of working without actually serialising anything, and the context…
Most decorators leave the function's outward shape alone. The same parameters go in, the same return type comes out, and inspect.signature and inspect.iscoroutinefunction give the same answers they would have given for the undecorated function. Sometimes you want a decorator that actively changes that shape. Adds or removes a parameter. Changes the return annotation. Turns a sync function into…
This post is for the people who write APM agents, tracers, profilers, debuggers, and anything else that instruments Python code without asking the user to change it. Everyone else is welcome along. The reason I want to call out the audience up front is that wrapt was created for this kind of work, and the original purpose is sometimes obscured by how widely the project has been adopted for its…
Following on from the previous post on stateful decorators , there is another small addition in wrapt 2.2.0 worth a closer look. A new wrapt.lru_cache helper has been added that fixes the long-standing issues with using functools.lru_cache on instance methods. The thing I want to emphasise up front is that wrapt.lru_cache is not a replacement for functools.lru_cache . The actual caching is still…
A new version of wrapt was released earlier this week. Version 2.2.0 introduces a small helper that makes it noticeably easier to write decorators that need to keep state across calls. It is the kind of thing that does not look like much until you try to write the equivalent code without it, so it is worth a closer look. The full release notes are in the changelog . What I want to walk through…
I've been working on a set of interactive workshops on Python decorators and they are now available for free on the labs page of this site. There are 22 workshops in total, covering everything from the fundamentals of how decorators work through to advanced topics like the descriptor protocol, async decorators and metaclasses. The workshops are hosted on the Educates training platform and accessed…