April gave Python developers a new governing body. PEP 772 was accepted on April 16, creating a dedicated Python Packaging Council that will make binding decisions about packaging standards and tools. After years of informal coordination through the Python Packaging Authority (PyPA), the packaging community now has its own elected five-member council with authority comparable to the Steering Council.
On the release side, Python 3.15.0 alpha 8 dropped with a refreshed JIT delivering 6–7 percent speedups on x86-64 Linux and 12–13 percent on AArch64 macOS. The core team also decided to revert 3.14’s incremental garbage collector after production reports of runaway memory use, with the fix landing in the upcoming 3.14.5 patch release. The next pre-release is the first beta, scheduled for May 5, which marks the feature freeze for Python 3.15.
Elsewhere, Google released the open-weights Gemma 4 family, Starlette 1.0 shipped for FastAPI’s foundation, and the broader Python ecosystem absorbed the news that OpenAI acquired Astral, the company behind uv, Ruff, and ty. Get ready to dig into the biggest Python news from the past month!
Join Now: Click here to join the Real Python Newsletter and you’ll never miss another Python tutorial, course, or news update.
Python Releases and PEP Highlights
April pushed Python 3.15 to its final alpha before the beta freeze, walked back the incremental garbage collector introduced in 3.14, and gave the Steering Council a busy month of PEP decisions. The packaging community even got its own elected governing body for the first time. Plenty to unpack on the language and process side of the ecosystem.
Python 3.15.0 Alpha 8: Final Alpha Before Beta Freeze
Python 3.15.0a8 landed on April 7, released alongside maintenance updates 3.14.4 and 3.13.13. Release manager Hugo van Kemenade confirmed that a8 is the final alpha before the beta phase begins. If you maintain a library, this is the last alpha where you can file an issue against an unreleased feature and reasonably expect it to land before the freeze.
Alpha 8 consolidates a long list of PEPs you’ve been hearing about in earlier alphas:
- PEP 810: Explicit lazy imports, which we covered last month
- PEP 814:
frozendictas a built-in type - PEP 799: Statistical sampling profiler
- PEP 798: Unpacking in comprehensions
- PEP 686: UTF-8 as the default encoding
- PEP 728: TypedDict enhancements
The headline number is the JIT performance jump. On x86-64 Linux, the alpha reports a 6–7 percent geometric mean improvement over the standard interpreter. On AArch64 macOS, the gain is 12–13 percent over the tail-calling interpreter introduced in 3.14. Those aren’t microbenchmark curiosities. They’re cumulative gains across a broad suite of workloads.
Note: If you haven’t tried the alpha yet, installing it in an isolated environment is a good idea. Running uv python install 3.15.0a8 pulls the binary, and pyenv handles alpha builds too. The next pre-release, 3.15.0 beta 1, is scheduled for May 5, which marks the feature freeze. After that, no new PEPs land in 3.15.
Incremental GC Reverted in 3.14.5 and 3.15
On April 16, release manager Hugo van Kemenade proposed reverting the incremental garbage collector that debuted in Python 3.14, and the core team agreed. The revert will ship in Python 3.14.5 and also make it into 3.15 before feature freeze.
The reasoning is practical. Neil Schemenauer’s testing on production workloads showed that the incremental collector cut maximum pause times from 26 ms down to 1.3 ms, which looks great on paper. But peak memory usage climbed to as much as 5x the generational baseline in the worst case, and total runtime went up, not down, because of the extra bookkeeping.
For most Python programs, like web apps, data pipelines, and batch jobs, reducing long pauses isn’t the win that matters. Memory pressure is.
The unusual part is doing this in a patch release. The working assumption during 3.14’s release cycle was that the incremental GC had earned its place. Rolling it back in 3.14.5 is a reminder that “passed the benchmark suite” and “works in production” aren’t the same thing. If you noticed your 3.14 deployments using noticeably more memory than 3.13, this is almost certainly why, and 3.14.5 should give you the old behavior back.
Note: The incremental approach isn’t dead. The core team noted that it could return in Python 3.16 through a proper PEP review process, which the original implementation had skipped. If you were on the fence about the switch, waiting for the formal design round is probably the right call.
PEP 772 Accepted: Python Gets a Packaging Council
On April 16, the Python Software Foundation (PSF) and the Steering Council accepted PEP 772, which creates a five-member Packaging Council with broad authority over packaging standards, tools, and implementations. It’s one of the biggest governance changes the ecosystem has seen since the Steering Council itself was established back in 2019.
Council members will be elected by PSF voting members who opt into the election. The council runs on staggered two-year terms, with two seats and three seats rotating in different cycles to preserve institutional continuity. Decision-making emphasizes consensus over voting, following the same pattern that has worked for the Steering Council.
The practical impact is that a formal, elected body now owns decisions about tools like pip, setuptools, and PyPI, replacing the ambiguous delegation model defined in PEP 609.
If you’ve ever wondered why packaging decisions in Python sometimes feel stuck in committee, PEP 772 is the structural answer to that complaint. It also sets the stage for the council to weigh in on LLM-era packaging concerns, which are popping up faster than the PyPA’s informal coordination could address them.
PEP 803 Accepted: Stable ABI Goes Free-Threaded
PEP 803 was accepted on March 30 and targets Python 3.15. It defines abi3t, a new variant of the stable ABI that works with free-threaded builds. When the Steering Council accepted PEP 779 last year, it promised free-threading would get a proper stable ABI story for 3.15. PEP 803 is that follow-through.
The problem abi3t solves is concrete. If you maintain a compiled extension and want it to work on free-threaded Python today, you ship a separate wheel for every version of every Python release you support. The regular abi3 contract (write once, run on any 3.x) doesn’t apply, because the free-threaded build has different invariants.
Big downstream projects like Cryptography, SciPy, and Pydantic have been flagging the wheel-explosion problem for over a year.
The tradeoff comes from making PyObject opaque under abi3t. Extensions that reach into PyObject fields directly will need to migrate to the newer accessor APIs from PEP 697 and PEP 793. That’s a real refactor for some projects, but it pays off with a forward-compatible story across Python versions.
If you follow the free-threading rollout closely, pair this with FastAPI 0.136.0 declaring official support for Python 3.14t, also this month. The infrastructure layer for GIL-free Python is maturing quickly.
PEP 800 Accepted: Disjoint Bases in the Type System
PEP 800 was accepted on April 15 and targets Python 3.15. It adds a new @typing.disjoint_base decorator that marks a class as incompatible with other disjoint bases for multiple inheritance purposes.
The decorator is mostly useful in stub files for C-implemented classes in the standard library, where shared subclassing is forbidden at runtime but the type system has no way to express that:
from typing import disjoint_base
@disjoint_base
class Disjoint1:
pass
@disjoint_base
class Disjoint2:
pass
# Type checker error: cannot inherit from two unrelated disjoint bases
class Invalid(Disjoint1, Disjoint2):
pass
At runtime, the decorator just sets __disjoint_base__ = True on the class. The real work happens in type checkers like mypy and Pyright, which use the marker to flag impossible class hierarchies and unreachable isinstance() branches. Stub authors for standard library C extensions are the primary audience, but the decorator is available via typing_extensions for older Python versions, too.
PEP 829 Draft: Replacing .pth Files for Package Startup
On March 31, Barry Warsaw submitted PEP 829, which proposes a new .start file format to replace the legacy .pth file’s ability to execute arbitrary code during Python startup.
Today, .pth files in your site-packages can do two things. They can extend sys.path by naming directories, and they can run arbitrary code via import lines, which Python processes through exec(). The second behavior is a known supply-chain risk. A malicious package can inject startup code that runs the moment Python starts, with no explicit opt-in from the user. PEP 829 proposes splitting the two jobs:
# mypackage.pth (still allowed)
path/to/additional/source/dir
# mypackage.start (new, replaces import lines)
mypackage.sitecustomize:install
The .start file uses the familiar package.module:callable entry-point syntax that setuptools and importlib.metadata already use. Arbitrary exec() goes away. Packages that currently rely on .pth for startup hooks would migrate to .start during a three-year deprecation window. Pytest plugins, coverage.py, and import-time patching libraries are the usual suspects.
Note: If you maintain a package that uses .pth files for anything other than adding paths, then this is the PEP to track. It’s still a draft, but the security motivation is strong enough that some form of the proposal is likely to land.
Other PEPs Filed in Draft
A handful of smaller PEPs appeared in draft form this cycle, mostly pointing at Python’s observability story:
- PEP 830 proposes adding a
__timestamp_ns__attribute toBaseExceptionso that formatted tracebacks can display when each exception was instantiated. Opt-in viaPYTHON_TRACEBACK_TIMESTAMPSor-X traceback_timestamps. Useful the next time you’re correlating a traceback against a multi-service log stream. - PEP 831 asks the core team to compile CPython with
-fno-omit-frame-pointerby default, which would make eBPF profilers (bpftrace, Pyroscope, Parca) able to unwind Python stacks without workarounds. The authors peg the runtime overhead at 0.5–2.3 percent, against profiling wins they measure at 5–500 percent. - PEP 832 sketches a standard way for tooling to discover the “current” virtual environment, instead of every launcher and IDE reinventing its own convention.
None of these have Steering Council decisions yet, but together they hint at where CPython’s production-debugging story is headed.
Community and Ecosystem Highlights
Governance changes, a company acquisition, and the end of a beloved collaborative maintenance experiment. April was a busy month for Python’s infrastructure beyond the code itself, and each of these stories points at a different question about the people and structures behind Python’s infrastructure.
OpenAI Acquires Astral
In late March, OpenAI announced the acquisition of Astral, the company behind uv, Ruff, and the emerging type checker ty. The news traveled through the community in April as developers worked out what it means for tools that have become load-bearing infrastructure. Chris and Chris discussed it on the podcast at the end of March, and the ripples are still visible in PyCoder’s Weekly clicks.
The scale of the deal is hard to overstate. Earlier this year, uv crossed 126 million monthly downloads. Ruff is the default linter and formatter for a huge slice of modern Python projects. Moving both tools under OpenAI’s ownership is a real shift in who controls critical Python infrastructure.
Simon Willison’s take was cautiously optimistic. He trusts the Astral team’s current intentions, but he also points out that “a product+talent acquisition can turn into a talent-only acquisition later on.” The permissive licensing of the tools makes forking a viable fallback, which is the structural safeguard the ecosystem still has.
In practice, the first full month of post-acquisition Astral development was boring in the best way. uv shipped patch releases 0.11.3 through 0.11.7, Ruff shipped 0.15.9 through 0.15.11, and neither project changed direction. If you were nervous about a sudden pivot toward Codex-only integration, that hasn’t happened yet.
Note: If you want to understand the tools before speculating about their future, Real Python’s uv tutorial and Ruff tutorial walk through what they do and how they fit into modern Python workflows.
Jazzband Is Shutting Down
On March 14, Jannis Leidel announced that Jazzband, the collaborative maintenance organization for Python open source, is winding down. New signups are disabled immediately, project leads will be contacted before PyCon US to coordinate transfers, and the GitHub organization will stay online through the end of 2026.
Jazzband launched in 2015 as a way to reduce the one-maintainer-burnout pattern. Members got shared push access to 84 projects, including django-debug-toolbar, sorl-thumbnail, pip-tools, and dozens of other widely used packages. Over its decade, Jazzband grew to 3,135 members with roughly 93,000 GitHub stars combined.
Two reasons drove the decision. The first is what Leidel calls the “slopocalypse”, the flood of low-quality AI-generated pull requests on GitHub that made shared push access increasingly risky. The second is the familiar story of volunteer burnout. Jazzband was effectively a “one-roadie operation” that depended on Leidel managing permissions and infrastructure, and the volunteer succession plan never fully materialized.
Django Commons is the suggested new home for Django-adjacent projects. Non-Django packages will need to find alternative communities or move to individual maintenance. It’s a sober reminder that the open-source maintenance problem isn’t solved, and new AI-driven noise is actively making it harder.
Library and Tooling Updates
Several headline libraries shipped releases worth catching up on during March and April. The recurring theme this round is maturity over novelty, with long-standing projects reaching 1.0, pushing their streaming engines further, or sharpening their security posture rather than chasing new features. Here are the updates that deserve a spot on your radar.
Starlette 1.0: A Foundation Turns Stable
Starlette 1.0 was released on March 22 after years of 0.x development. Starlette is the ASGI framework that powers FastAPI, and its 1.0 milestone means the API is now considered stable. If you’ve been building on FastAPI, this is the underlying contract you’ve been relying on for years, finally with a stability guarantee attached.
Practically, 1.0 isn’t a feature explosion so much as a promise that the existing API won’t break without a major version bump. That’s useful in its own right, because FastAPI applications frequently use Starlette’s routing, middleware, and testing utilities directly.
Polars 1.40.0: Streaming Engine Grows Up
Polars 1.40.0 shipped on April 18 with a streaming engine expansion that changes what kinds of workloads you can run in-process. Grouped AsOf joins, cov, corr, skew, kurtosis, entropy, and strptime all got lowered to the streaming engine. The release also ships a lock-free memory manager with spill-to-disk support, which means Polars can now handle datasets that don’t fit in memory without forcing you to switch to Dask or Spark.
The other change worth noting is the deprecation of the DataFrame interchange protocol. If your code relies on the __dataframe__ dunder for cross-library interop, start planning the migration path. Polars 1.40 also adds pl.merge_sorted for multi-frame sorted merging.
Other Notable Releases
- DuckDB released 1.5.0 on March 9 with SQL feature additions and performance improvements. If you haven’t tried DuckDB yet, the Polars and DuckDB combo is worth knowing about.
- PyPy 7.3.21 landed with bug fixes and compatibility updates for the alternative JIT-compiled Python runtime.
- FastAPI 0.136.0 added official support for free-threaded Python 3.14t on April 16. It’s one of the first major web frameworks to declare explicit GIL-free runtime support.
- Django released security patches 6.0.4, 5.2.13, and 4.2.30 on April 7, fixing five CVEs covering ASGI header spoofing, permission escalation in
GenericInlineModelAdmin, and DoS vectors in the multipart parser. This release also marks the end of Django 4.2’s support lifecycle, so if you’re still on 4.2, now is the time to plan a migration. - Claude Opus 4.7 was released by Anthropic on April 16, with same-day support in the Python SDK and in pydantic-ai v1.84.0. The SDK also added
token_budgetsanduser_profilesparameters for per-user cost controls.
AI Tooling Updates
Between Google’s Gemma 4 family, vLLM’s monthly cadence, and Anthropic’s Opus 4.7 drop, the AI ecosystem kept pace with its usual rhythm. A few items stand out for their direct Python developer impact, especially around open-weights model serving and the shift toward WebSocket-based streaming APIs.
Gemma 4 and the Day-One Python Ecosystem
On April 2, Google released Gemma 4, an open-weights multimodal family with 2B, 4B, and 31B dense variants plus a 26B Mixture-of-Experts flagship. The 26B MoE is the one to watch. It packs frontier-class reasoning into a model size that’s still tractable for serious inference workloads, and all variants handle images, video, and audio natively.
The day-one ecosystem integration is what makes this release different. Hugging Face Transformers 5.5.0 shipped on April 2 with Gemma 4 as its headline feature. vLLM v0.19.0 dropped on April 3 with full serving support. Ollama v0.21.0 followed with MLX quantization for Apple Silicon. If you remember the Llama 2 rollout back in 2023, when you had to wait weeks for usable Python tooling, you know how different this release cycle feels.
Loading a Gemma 4 checkpoint in Python now takes the same shape as any other Transformers model:
from transformers import AutoProcessor, Gemma4ForConditionalGeneration
processor = AutoProcessor.from_pretrained("google/gemma-4-E4B-it")
model = Gemma4ForConditionalGeneration.from_pretrained(
"google/gemma-4-E4B-it", device_map="auto"
)
# Accepts text, images, audio, and video
The dedicated Gemma4ForConditionalGeneration class and its matching processor handle all four input modalities out of the box, which is a big improvement over last year’s pattern of wiring up separate vision and audio preprocessors by hand.
vLLM 0.19 Adds Zero-Bubble Async Scheduling
vLLM 0.19.0 landed on April 3 with 448 commits from 197 contributors. The headline feature is zero-bubble async scheduling with speculative decoding overlap, which eliminates idle GPU cycles during token generation. CPU KV cache offloading is now generalized, and there’s a new /v1/chat/completions/batch endpoint for batched inference.
The security-minded additions are worth noting, too. A new VLLM_MAX_N_SEQUENCES environment variable caps concurrent requests, and video input frame limits prevent resource exhaustion attacks. A quick patch release, 0.19.1, followed on April 18 to fix Gemma 4 streaming tool-call bugs.
OpenAI SDK Gets WebSocket Reconnection
The OpenAI Python SDK shipped v2.31.0 on April 8 and v2.32.0 on April 15. Building on the WebSocket transport updates covered in March, v2.32.0 adds automatic reconnection, an event-handler-based WebSocket interface, and enqueue-while-disconnected support for the Realtime API. If you’re building voice or streaming apps on the Realtime API, these changes cut a meaningful chunk of boilerplate.
Conferences and Events
Spring conferences are in full swing, and summer planning is now urgent:
- PyCon US 2026 runs May 13–19 in Long Beach, California. The full schedule is now live: tutorials fill May 13–14, the main conference is May 15–17, and development sprints wrap up May 18–19. Registration is open.
- DjangoCon Europe 2026 wrapped up in Athens, Greece, on April 19. Talk recordings should be available on YouTube in the coming weeks.
- PyTexas 2026 wrapped up in Austin, Texas, on April 19. Recordings will be posted on their channel soon.
- PyOhio 2026 opened its Call for Proposals. PyOhio is a free regional Python conference and a great venue for first-time speakers.
- The Django Software Foundation put out a call for organizers for DjangoCon Europe 2027. If your local community has ever thought about hosting, the door is open.
Real Python Roundup
April’s Real Python lineup leans heavily toward AI-assisted Python. A Codex CLI deep-dive, a head-to-head between Gemini CLI and Claude Code, and a new field guide to the four kinds of AI coding agent workflows all landed this month. If you’ve been hopping between assistants without settling on one, the Python Coding With AI learning path pulls the pieces into a single curriculum you can finish instead of doomscrolling release notes:
Learning Path
Python Coding With AI
5 Resources ⋅ Skills: Claude Code, Cursor, Gemini CLI, AI-Assisted Development
The guiding principle behind the path is to pick one tool, get good at it, and resist the urge to treat “keeping up with AI tools” as a second job. It opens with a Simon Willison podcast on the mindset shift for LLM-assisted development and then branches into video courses on Claude Code, Cursor, and the Gemini CLI, plus the Claude Code for Python Developers live workshop.
Note: The next Claude Code Live Course runs May 6–7.
Join Real Python’s Philipp Acsany for a hands-on Claude Code masterclass in AI-assisted development. Over two sessions (4 hours each, via Zoom), Philipp will show you how to move beyond toy prompts and treat Claude Code as a legitimate pair programmer.
You’ll leave with a working project in your portfolio and a professional workflow you can put to work right away. Reserve Your Seat →
Sharpen your skills with these new written tutorials:
- Python Classes: The Power of Object-Oriented Programming
- Dictionaries in Python
- How to Add Features to a Python Project With Codex CLI
- Variables in Python: Usage and Best Practices
- Gemini CLI vs Claude Code: Which to Choose for Python Tasks
- Altair: Declarative Charts With Python
- How to Conceptualize Python Fundamentals for Greater Mastery
- AI Coding Agents Guide: A Map of the Four Workflow Types
If video is more your style, check out these new video courses:
Test your understanding with these new quizzes:
- Exploring Keywords in Python
- Python’s Counter: The Pythonic Way to Count Objects
- How to Add Features to a Python Project With Codex CLI
- Class Concepts: Object-Oriented Programming in Python
- For Loops in Python (Definite Iteration)
- Using Loguru to Simplify Python Logging
- Building a Python GUI Application With Tkinter
- Implementing the Factory Method Pattern in Python
- Reading Input and Writing Output in Python
- Exploring Protocols in Python
- Gemini CLI vs Claude Code: Which to Choose for Python Tasks
- Python Continuous Integration and Deployment Using GitHub Actions
- Vector Databases and Embeddings With ChromaDB
- Altair: Declarative Charts With Python
- Explore Your Dataset With pandas
- Design and Guidance: Object-Oriented Programming in Python
- Welcome to Real Python!
- Working With Python Virtual Environments
- Leverage OpenAI’s API in Your Python Projects
- uv vs pip: Python Packaging and Dependency Management
On The Real Python Podcast, host Christopher Bailey published three new episodes last month:
- Episode 290: Advice on Managing Projects & Making Python Classes Friendly
- Episode 291: Reassessing the LLM Landscape & Summoning Ghosts
- Episode 292: Becoming a Better Python Developer Through Learning Rust
If you’re thinking about where LLM-based tools fit into your workflow, Episode 291 features Jodie Burchell from JetBrains on the shift from post-training to context engineering and multi-agent orchestration. It’s a useful 75-minute primer on where AI tooling is actually landing in real development workflows.
Over on Episode 292, Bob Belderbos shares how learning Rust made him a better Python developer. The compiler forced him to confront patterns he’d been getting away with in Python.
What’s Next for Python?
Looking ahead, here’s a quick recap of what’s coming up:
- Python 3.15.0 beta 1 ships on May 5, marking the feature freeze. If you maintain a library, this is the version to test against for 3.15 compatibility.
- Python 3.14.5 will ship the incremental GC revert back to the generational collector. If your 3.14 deployment has been bloated, this is the patch to watch for.
- The Packaging Council will hold its first elections now that PEP 772 is accepted. Watch for announcements from the PSF about candidate nominations and the voting process.
- PyCon US 2026 runs May 13–19 in Long Beach. The full schedule is live, so you can start planning which talks to catch.
- PEP 822 (d-strings), covered last month, is still awaiting a Steering Council decision. A verdict before beta freeze would let d-strings ship in 3.15.
Packaging governance, a final alpha, and AI tooling that reshuffled its corporate parent. April was a month when the structural layer of the Python ecosystem got a lot of attention. If you’ve been treating your uv, Ruff, and pip as given constants, this is a good month to at least know who makes the decisions about them. If you’re going to PyCon US in May, maybe that’s the conversation to bring up in the hallway track. See you next month!
Join Now: Click here to join the Real Python Newsletter and you’ll never miss another Python tutorial, course, or news update.


