Planet Python
Last update: September 27, 2026 01:48 AM UTC
September 26, 2026
Python Insider
The Python documentation is now available in German
You can now read the Python documentation online in German!
September 26, 2026 12:00 AM UTC
September 25, 2026
Rodrigo Girão Serrão
TIL #146 – Using maturin through uv
Today I learned how to setup a Rust project that can be called from Python with PyO3 and maturin through uv.
When you follow the PyO3 getting started guide to create a simple Rust project that can be called from Python, the instructions you get assume you'll use a global Python installation to create a virtual environment and to install maturin into it.
You can use uv through maturin, but if your project also has a Rust binary, things may break.
When you run a command like cargo run, cargo will see the dependency on PyO3 and it will then look for a Python installation.
If you have no global Python installations — because you do everything through uv — or if your global installations aren't setup exactly like a vanilla, default installation, PyO3 might fail.
The fix is simple.
In .cargo/config.toml add the environment variable PYO3_PYTHON that points to the Python inside your virtual environment:
# .cargo/config.toml
[env]
PYO3_PYTHON = { value = ".venv/bin/python", relative = true }
How to set up a Rust + Python project with PyO3 and maturin through uv
Here are all the steps to set up a Rust project that can be compiled into a binary executable and that can also be used from within Python:
% cargo new calculator
% cd calculator
Create the file lib.rs:
// lib.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[pyo3::pymodule]
mod calculator {
use pyo3::prelude::*;
#[pyfunction]
fn add(a: i32, b: i32) -> PyResult<i32> {
Ok(crate::add(a, b))
}
}
And update the file main.rs to depend on your calculator:
use calculator::add;
fn main() {
println!("{}", add(1, 2));
}
If you run cargo run, you should get the result 3:
% cargo run
3
Add the PyO3 dependency from the Rust side:
% cargo add pyo3 -F abi3-py38
Update Cargo.toml to configure your crate type so it can be compiled for the Rust binary and for the Python bridge:
# Cargo.toml
# ...
[lib]
name = "calculator"
crate-type = ["cdylib", "rlib"]
Now, create a minimal pyproject.toml:
# pyproject.toml
[project]
name = "calculator"
version = "0.1.0"
[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"
Add the dependency on maturin and run it:
% uv add maturin
% uv run maturin develop
# ...
✏️ Setting installed package as editable
🛠 Installed calculator-0.1.0
Run Python with uv run python and test your package:
>>> from calculator import add
>>> add(3, 4)
7
At this point you're happy that you can use your Rust code from Python and may not realise that cargo run may no longer work, complaining about Python frameworks, not finding whatever it needs to link, or other weird errors.
Configure cargo to use the Python installation from the virtual environment by adding the file .cargo/config.toml:
# .cargo/config.toml
[env]
PYO3_PYTHON = { value = ".venv/bin/python", relative = true }
Try running cargo run again and note that everything still works:
% cargo run
3
Fixing issues with PyO3 +
...September 25, 2026 08:34 AM UTC
LernerPython blog, from Reuven Lerner
Pandas dropna: The best way to remove NaN values from a series
Coming to Python Pandas from NumPy? You’ll reach for np.isnan: Unfortunately, this works. Better, use s.isna (or s.isnull). But the best way to drop NaN? Use dropna:
The post Pandas dropna: The best way to remove NaN values from a series appeared first on LernerPython.
September 25, 2026 06:00 AM UTC
Glyph Lefkowitz
Who Is Open Source About?
Open source comprises a complex social web of ongoing relationships, not a simple one-way “gift” of value from maintainer to user.
September 25, 2026 12:50 AM UTC
Graham Dumpleton
A master class in decorators, patching and tracing
There is now a Workshops page on this site listing seventy free hands-on workshops, spread across five collections. They start with how decorators work in plain Python using nothing but the standard library, move on to what wrapt adds for decorators, monkey patching and object proxies, and finish with patching, testing and tracing real code using wrapture. Taken in order they amount to a master class on the subject, and you don't need anything installed to work through them.
Why I have been making these
My working life is in an odd place at the moment. I am on what has turned into an extended sabbatical, and I still haven't decided whether it ends with going back to a job or with retiring for good. The upside is that I have time to spare, and I have been putting it to use filling out the documentation and learning material for my open source projects, something that has always lagged well behind the code.
The other reason is that decorators, monkey patching and instrumentation are topics I have probably spent more time on than most people ever will. I have been maintaining wrapt for well over a decade, and it grew out of the monkey patching I wrote for the New Relic Python agent before that. A lot of what I learned along the way only exists in my head, or is scattered across old blog posts and issue discussions. Workshops are a way of getting that knowledge out in a form people can actually learn from, rather than it disappearing with me.
Starting with the standard library
The first collection is 14 Python decorator workshops. These replace the decorator workshops I announced back in April, which were hosted on Educates, with a rewritten and more focused set.
They use only the standard library. The first has you use decorators before writing one, putting a few from the standard library to work to find out what the @ line actually means. From there you write your first decorator, find out how a wrapper remembers the function it wraps, give decorators arguments, and see what functools.wraps does and doesn't fix. The middle of the collection deals with stacking decorators and with methods, which is where most decorators people write start to go wrong. That includes working out how obj.method() finds its instance by doing the binding by hand, since that is what explains why a class based decorator can't be used on a method without extra work. The last few are practical: decorating classes, caching results, registering functions the way Flask, Click and pytest do, retrying and handling errors, and decorating async functions.
Decorators, patching and proxies with wrapt
In the April post I said the natural follow on would be a course built around wrapt. That has now happened, as three collections in the wrapt workshops.
The first collection, of 12 workshops, covers writing decorators with wrapt. Each workshop puts the wrapt version beside the standard library version it replaces, so you can see what each one gives you. It starts with the wrapper function wrapt expects and what the instance argument tells you about whether you are decorating a function, an instance method, a class method, a static method or a class. Later workshops cover keeping state in a decorator, switching a decorator off, validating arguments, per instance caching of methods, synchronising calls across threads and in async code, and changing the signature a decorated function reports.
The second collection, of 10 workshops, is on monkey patching code you didn't write. It covers patching every kind of method, taking a patch out again, patches which only last for a block of code, why a patch applied correctly can still do nothing, applying a patch before the target module has even been imported, and patching instance attributes. It ends by putting all of that together into the shape every instrumentation agent ends up having.
The third collection, of 10 workshops, is on object proxies, where one object stands in for another. You start by writing a delegating class by hand and seeing what it gets wrong, then find out what a proxy passes through to the object it wraps and what it deliberately doesn't. From there it covers intercepting special methods, the function wrapper that sits under every wrapt decorator, lazy proxies used for deferring imports, holding a function weakly, and pickling and copying a proxy.
Patching, testing and tracing with wrapture
The final collection is the 24 wrapture workshops, which I first mentioned when wrapture reached its first beta. They build on everything before them and range quite widely.
For testing, they cover writing unit tests by wrapping the real code rather than replacing it, recording what the real code did and turning that into a test, behaviour that changes over time, async code and generators, using wrapture properly with pytest, and converting an existing test suite that uses unittest.mock. For tracing, they cover a program narrating its own calls, tracing a program without changing it, analysing a trace in a notebook, recording each request to a Flask application as a tree of calls, finding slow code, exporting to OpenTelemetry, and following one trace across two processes. They also return to monkey patching as a discipline, changing what a third party library does in a way you can reverse, and finish with writing an instrumentation package for a library nobody has covered yet.
You don't need to do them all
Although the collections form a path from start to finish, nobody needs to work through all of them. If you are fairly new to Python, the decorator workshops, plus the first few of the wrapt decorator workshops, are probably all you will want. The later wrapt workshops, and much of wrapture, go into territory most Python developers never need to visit.
Equally, you can just pick out whatever looks interesting, or whatever covers a problem you have right now. If you already know decorators and need to patch a library you don't control, start with the wrapt monkey patching workshops. If you want better tests, or need to understand what a running application is actually doing, go straight to wrapture. Within a collection the workshops are ordered so each builds on the one before, but you can jump in anywhere.
How the workshops are hosted
Each set of workshops lives in its own repository on GitHub. The workshops run in JupyterLab using jupyterlab-workshop, an extension I wrote which puts the workshop instructions in a side panel beside the notebooks, terminals and files you work with. I wrote about it in Introducing jupyterlab-workshop, and about how a workshop is put together in Writing a workshop for JupyterLab.
When you open a collection, the extension shows its workshops in the order to take them, what each covers, and how far you have got with each.

Opening a workshop puts its instructions in the side panel. Actions in the instructions do things in the session for you, such as creating a notebook or running a cell, and checks confirm you have done a step before you move on.

There are a few ways to launch a collection, and the page for each collection on this site has buttons for them. The decorator workshops can run entirely inside your browser using JupyterLite, where Python itself runs in WebAssembly. Nothing runs on a server, and your work is kept in your browser's storage between visits. That is what the second screenshot above shows. For now only the decorator workshops run this way.
Every collection can also be launched on mybinder.org, a free public service which needs no account. It builds the repository into a temporary JupyterLab session, which can take a minute or two, and the session is discarded when you finish. Alternatively, GitHub Codespaces runs the same setup under your own GitHub account, using your Codespaces allowance, and keeps the codespace around until you delete it. If you would rather use your own machine, the README in each repository explains how to run the workshops locally.
What comes next
These collections will keep being refined, and I would like to hear about anything which is confusing or wrong. The GitHub repository for each collection is the place to raise an issue.
Beyond these, I plan to do workshops on WSGI and mod_wsgi, which is the other area where I have years of accumulated knowledge that has never been written down properly. I also want to look at what workshops I could create for people newer to Python, alongside the more detailed ones I have been doing so far. If there is a topic you think is badly served by what is already out there, let me know.
September 25, 2026 12:00 AM UTC
September 24, 2026
PyCon
PyCon US 2026 Recap and Recordings
September 24, 2026 02:38 PM UTC
Django Weblog
DSF member of the month - Ken Whitesell
For September 2026, we welcome Ken Whitesell as our DSF member of the month! ⭐

Ken has long been part of the Django community, serving for many years as an helper in the Django forum and recipient of the Malcolm Tredinnick Memorial award. He has been a volunteer for DjangoCon US for over ten years. He is a DSF member since September 2017!
You can learn more about Ken by visiting Ken's blog and his GitHub Profile.
Let’s spend some time getting to know Ken better!
Can you tell us a little about yourself? (hobbies, education, etc)
Hi everyone! I've been retired for a little more than a year now. After 45 years working in software development, I'm now free to spend my time working on what interests me. (You could say that what used to be my hobby is now my profession.) I'm currently living in the mountains about 60 miles south-east of Pittsburgh.
I mostly consider myself a boardgamer. Boardgaming has been a serious hobby for me for more than 50 years now, and has been one of the driving forces in my personal development as a programmer. Not in terms of programming or developing games, but doing analysis. I enjoy looking at the probabilities and patterns that may exist in particular games. To a lesser extent, I'm starting to develop an interest in using AI to create computer opponents.
My education was primarily informal. I had a BASIC class in high school, along with a touch of Fortran and COBOL. College didn't go nearly as well - I withdrew about mid-way through my first semester. (I guess I would say that I really wasn't ready for it on a number of different levels.)
About nine months later, I enlisted in the US Air Force. That's where my education really took off. I had a variety of experiences that exposed me to technologies that I wouldn't have otherwise been able to see. The training opportunities were amazing, and I'd like to think I took advantage of most of them. Beyond that, the rest of my education has been primarily self-directed.
How did you start using Django?
I was first exposed to Django at the first PyCon after it was released, but my job and other interests prevented me from looking at it in detail. It wasn't until 2014 when I took a job to help build a system using it that I got serious about learning it.
What other framework do you know and if there is anything you would like to have in Django if you had magical powers?
Oh my. We could split a lot of hair trying to define "framework" and "know". To some degree of knowledge I've worked with Drupal, WordPress, Joomla, CherryPy, Nevow, Spring, meteor.js, LifeRay, ASP.NET, and Zope. (There may be others that I've worked with but don't remember right off-hand.)
Aside from my professional responsibilities, my pet project is something I've been trying to do for more than 20 years. I've looked at a large number of frameworks
Is there anything from those other frameworks I'd like to have? I've never honestly thought about it in those terms. Every other framework I've used has come up short in at least one area I consider critical - that's why I've looked at so many of them.
I won't say that Django is perfect, but it is a perfect fit for me, how I look at the web, what I want to do, and how I want to approach those solutions. It's the closest match to how I think. I encounter a lot less friction when trying to get stuff done with Django than I ever had in any other framework.
What projects are you working on now?
My primary project is my boardgame-playing engine. I've got a handful of games that I enjoy playing, but are ignored by the "mass market" sites such as Boardgame Arena and Tabletop Simulator. I'm doing browser-based ports of them to support competitive play of those games. I also have a couple websites I maintain for my boardgaming community.
Which Django libraries are your favorite (core or 3rd party)?
First and most important to me is Channels. My boardgame site wouldn't exist if I didn't have a "Django-friendly" way of using websockets. Related to that, but not a Django library, would be HTMX. It provides the browser-side of the websocket connection in a way that works for me.
Beyond that, I rely heavily upon Django Crispy Forms, Django Extensions, and Treebeard.
What are the top three things in Django that you like?
Top of the list is the basic fact that it's written in Python. Given the choice, I'll pick working in Python over any other language.
Next is the ORM. I don't mind working with SQL, but I appreciate the layer that builds objects from the results.
Last of the three would be forms, both their ability to render HTML and to validate input.
You have been helping community members in the Django forum for many years and for some time in Django Discord. Thank you so much for your help. What made you start helping people in the first place and keep doing it?
Community has always been important to me. When I went to my first DjangoCon in 2014, I knew I had a lot to learn. Fortunately, there were a number of Djangonauts willing to spend their time helping me get past a number of conceptual hurdles.
At DjangoCon 2018 and 2019, Carlton Gibson gave talks titled "Your web framework needs you!" They were more than inspiring, they were reminders to me that as a member of this community, I had a responsibility to help keep it going. (In my case, that meant doing more than just working the registration desk.) I started looking for ways that I might be able to contribute.
Also in 2019, Andrew Godwin announced that the Django Forum was launched. I had been reading the mailing lists, but I wasn't particularly thrilled with that as a medium for discussion. I was looking forward to the forum becoming an active venue. I wasn't active at first - I didn't have any specific questions needing to be asked and there weren't any questions posted where I felt confident enough to answer them.
We all know what 2020 brought. In my case, it brought a lot of free time I wouldn't have otherwise had. In Feburary, I saw a question I felt comfortable answering. Then in March, I saw a couple more. I did my best to answer them. Since I wasn't getting corrected or told that my comments were unwelcome, I kept going. (Even after working with Django for 5 years at that point, I still wasn't all that comfortable with my understanding of a number of concepts.) Then during that summer when all my other plans had gone out the window, it became a major part of my day. I also began to realize that I was actually contributing to the Django Community and it felt good! I knew that I would never be able to really contribute code. But I also thought if I spent my time answering questions, then the people working on the code wouldn't feel the need to do that, and so indirectly I was helping move things forward by reducing at least one roadblock from their path.
So that became my motivator. I doubt I'll ever submit a PR. But if I can do anything that helps the Fellows or the other significant developers move Django forward, I'm going to be quite happy with that.
My activity on Discord is rather limited. For quick questions or open ongoing discussions I guess it's ok. But it would be my last choice of a platform to try and help someone with a detailed technical question.
You are a Malcolm Tredinnick Memorial award recipient, could you tell us a bit more about this award and what does it mean to you?
As far as the award itself, I think the Django docs say it best:
The award will be ... awarded annually, to the person who best exemplifies the spirit of Malcolm’s work - someone who welcomes, supports and nurtures newcomers; freely gives feedback and assistance to others, and helps to grow the community.
What does it mean to me? I see it primarily as validation and inspiration. It's validation that I think I am generally successful with what I'm trying to do. And it's inspiration for me to keep doing it. It's that little voice in me that says "Yes, what you're doing is worthwhile. You are helping people."
As far as knowing him, no. I was not fortunate enough for that to be the case. Malcolm passed in 2013, before I started really using Django. However, it's almost certain that I "met" him at least once while working at the PyCon registration desk from 2005 - 2010. But about the only thing I would have said to him would have been "Hi! Welcome to PyCon! Your name please?"
You are recently part of the security team, how have you seen Django security evolve through time?
To be honest, I'm not sure I'd describe it as "evolving" as much as simply "growing". One of Django's strengths to me has always been its focus on creating a secure environment. As far as I can tell, the project has always worked toward the ideal of "Security by design". And, when vulnerabilities are exposed, they get fixed. So I don't see it so much as anything is changing - just that the amount of work is increasing.
This is a process that has become more difficult through the years as Django continues to grow. The Django project has always been fortunate in that there have been some really amazingly astute people working to keep Django secure in the face of ever-increasing threats created by bad actors and AI. I'm just hoping to be able to help maintain that effort.
You know and have used Django for long time, do you have any advice for new learners or any Django user/developer?
For new people, my pet catch-phrase is "Don't fight the framework". Learn how Django does things, and adapt your mindset to match it. Do things the Django way. Don't try to make Django look or act like whatever framework you've used before. Once you really understand what's going on, if you want to make changes, fine. But ensure you understand the implications of those changes before making them.
Also, never forget that Django is Python. Nothing will help you understand Django more than having a very strong foundational understanding of Python.
What do you think of the evolution of Django through the years?
I think the stability and consistency through the years has been absolutely amazing. I could probably pull out some of the code I wrote in 2014 for Django 1.4 and have it running today with almost no effort. Django has done a wonderful job of moving things forward without unnecessarily throwing things away from the past. This stability is one of the reasons why I appreciate Django as much as I do.
After so much time in the Django community, what makes you stay?
It's the community itself, primarily the DjangoCon community. (Yes, I know that the Django community is significantly larger than just those attending DjangoCon, but my interactions with the community primarily revolve around DjangoCon, the forum, and (now) Discord.)
People come and people go. I miss some people that came to DjangoCons 10+ years ago, but I'm meeting new people every year - and that feeling doesn't change. There's something special about us, where everyone is open to share thoughts and ideas, and being friendly and helpful when doing so.
I start looking forward to the next DjangoCon the day after the previous one ends. How do you envision the future of Django from your perspective?
Technically, mostly stable with some gradual improvements. I don't see the possibility of any change being introduced that would make me want to make major changes to what I have running today. If something were to fundamentally change within Django that would break my existing system, I'd probably stay on 6.1 until I couldn't run it any more.
Is there anything else you’d like to say?
Thank you for inviting me to share my story!
Thank you for doing the interview, Ken !
September 24, 2026 02:13 PM UTC
LernerPython blog, from Reuven Lerner
New on the LernerPython practice system: A visual debugger
I’m a big fan of exercises, which is why the LernerPython platform includes hundreds of them — all using my in-browser practice system, which handles Python, Pandas, and Git, along […]
The post New on the LernerPython practice system: A visual debugger appeared first on LernerPython.
September 24, 2026 08:42 AM UTC
September 23, 2026
LernerPython blog, from Reuven Lerner
PyArrow dtypes in pandas: Nullable integers with pd.NA
PyArrow dtypes in Python Pandas are nullable (with pd.NA): s is: 0 101 <NA>2 30dtype: int64[pyarrow] The dtype is int64, but allows nulls. (Use np.nan? It’s turned into pd.NA.)
The post PyArrow dtypes in pandas: Nullable integers with pd.NA appeared first on LernerPython.
September 23, 2026 06:00 AM UTC
Python GUIs
Dynamically Adding Rows of Widgets in PyQt6 — How to use QGridLayout to add multiple widgets per row at runtime
I have a GUI where I dynamically add a QLineEdit for each image a user selects. That part works. But now I want to extend it so that each image gets a row of three text boxes — one for the filename, one for the width, and one for the height. How do I dynamically add multiple widgets horizontally for each new entry?
September 23, 2026 06:00 AM UTC
Python Bytes
#497 Faster than light profiling
Topics include Tachyon: A sampling profiler ships in Python 3.15's stdlib, Python Workers are now generally available on Cloudflare, Flet 1.0 - build cross-platform apps in Python, and marimo-book: Build static books from marimo notebooks.
September 23, 2026 03:45 AM UTC
Python Insider
The Python documentation is now available in Persian
September 23, 2026 12:00 AM UTC
September 22, 2026
PyCoder’s Weekly
Issue #753: frozendict, pytest Plugins, re.prefixmatch(), and More (2026-09-22)
September 22, 2026 07:30 PM UTC
Talk Python to Me
#564: EVE Online Departs for Python 3
Every ship in EVE Online eventually undocks and leaves the station. This time, it's the whole game. EVE has run on Python 2 since it launched in 2003, all 2.4 million lines of it, on a custom Stackless interpreter that stopped at 3.8 and was archived last year. Destination: Python 3.12. The route runs through 6,500 lines of division that decide who wins a fight, and 100 gigabytes of pickled Python objects that have to survive the jump intact. Kristinn Sigurbergsson was on this show ten years ago. He's back, with Jamie Bannister, who is flying the EVE Online migration right now, and Thomas Dähling, who took EVE Frontier through first. In EVE, a destroyed ship is gone for good. There are no do-overs, and the universe has to stay online the whole way.
September 22, 2026 06:24 PM UTC
Django Weblog
New Technical Governance Approved
Both the Steering Council and DSF Board have approved DEP 19, which implements our new technical governance. Thank you to everyone who read the document and participated in the process! This was the effort of two different DSF boards and dozens of community members.
These changes were a revisitation of Django’s technical governance in which a simplification and reduction was made to make it more approachable to more people.
The most exciting change (in my opinion), is the new Steering Council Eligibility criteria. We defined a set of wide range qualities that members of the Steering Council could possess that would be advantageous. The hope is that this helps community members realize they are qualified to be a Steering Council member and stand for election.
The next steps are to update the documentation in the Django and djangoproject.com repositories with any necessary updates. After that the DEP will move to the final state and folder.
September 22, 2026 11:00 AM UTC
LernerPython blog, from Reuven Lerner
Pandas nullable integers: Keeping ints with Int64 and pd.NA
You have a Python Pandas series with ints + NaN. You don’t want float forced on you. Solution: Use the “extension” type Int64 (note Initial Caps) and pd.NA: s is: […]
The post Pandas nullable integers: Keeping ints with Int64 and pd.NA appeared first on LernerPython.
September 22, 2026 06:00 AM UTC
September 21, 2026
Andre Roberge
Breaking a four year hiatus to talk about the export keyword (PEPs 842 and 843)
September 21, 2026 05:24 PM UTC
September 20, 2026
LernerPython blog, from Reuven Lerner
Get Python help, one on one: my coaching sessions
Some of the most satisfying work I do happens one on one. You arrive with a real problem from your real job — code that will not behave, an architecture […]
The post Get Python help, one on one: my coaching sessions appeared first on LernerPython.
September 20, 2026 10:37 AM UTC
NaN in Pandas: Why you need np.nan, not pd.NaN
Missing data? NumPy calls it nan. Python Pandas displays it as NaN. But: Pandas doesn’t define pd.nan or pd.NaN. NumPy removed np.NaN in version 2.0. So you have to refer […]
The post NaN in Pandas: Why you need np.nan, not pd.NaN appeared first on LernerPython.
September 20, 2026 06:00 AM UTC
September 19, 2026
Bob Belderbos
Ship Your First Python App: a Free Course on the Local Dev Workflow
I keep hearing this a lot: the Python syntax I picked up in an afternoon, but shipping a real project meant learning ten more things. There is a stark difference between writing some code in Python vs building an app that someone else can run on their system. These skills are taught, but rarely together in one place. So I am building a free course to teach this.
September 19, 2026 12:00 AM UTC
September 18, 2026
Django Weblog
Proposed change to DSF voting membership
We're proposing a new voting membership status to help us track active members. If you've voted in a Board election in the last two years, you're active, and you count toward quorum. If you haven't, you're still a member, but you won't count toward quorum until you tell us you want to vote.
Why make this change?
Quorum today is measured against every member on the rolls, including members who no longer take part in elections. As membership grows, quorum becomes harder to reach and puts our elections' validity at risk.
Defining a quorum around active members is standard practice for nonprofits. Counting the entire membership roll is the outlier.
The Python Software Foundation takes a similar approach. Its voting members are asked to affirm that they intend to vote, and in June 2024 the PSF board approved waiving that affirmation for anyone who voted in the previous board election (board minutes).
No one loses their membership under this change. You remain a member and stay listed on the website. Active status only affects how we count quorum. This keeps our rolls accurate and our elections valid.
We don't want anyone excluded because they missed an email. We'll send reminders before each election and post on our blog and the forum, so everyone has plenty of notice. If you want to vote, contact us before the election opens, and we'll add you to the roll.
We've proposed the corresponding bylaw change on GitHub, discussed this proposal on the Django Forum for a while, and talked it through in person at DjangoCon US.
Next steps
This is a call for public comment. Please share your feedback by October 7, 2026, either on the pull request or, if you're a DSF member, in the members-only Forum thread.
The Board will review the comments, and if the community raises no major objections, the Board will vote on the change at our October 8th Board of Directors meeting.
September 18, 2026 05:00 PM UTC
PyPy
PyPy v8.0.0 release
PyPy v8.0.0: release of python 2.7, 3.11, and 3.12 beta released 2026-09-19
The PyPy team is proud to release version 8.0.0 of PyPy after the previous release on May 26, 2026. This is a major new version, hence the bump to 8.0.0. It is our first release of Python 3.12, which may still have some bugs so we are calling it "beta" quality.
Why the move to 8.0.0
glibc2.28
We have updated our linux buildbots (linux64, linux32, aarch64) to use manylinux_2_28 images based on AlmaLinux 8 and glibc 2.28. These use gcc14 instead of the gcc5 previously used. So our compiled tarballs will require at least glibc2.28, which should be universally supported by now (Ubuntu 24.04 uses glibc2.39). In order to prevent confusion, we felt bumping the major version would be prudent.
cp12-abi3 support
PyPy's Python 3.12 support comes with a new model for the C layer PyObject.
In order to link the C object to the internal RPython one, we have an extra
field in the object ob_pypy_link, as described in-depth in
rawrefcount-and-the-gc. In previous versions, this field was
visible in a way that makes the PyObject struct different from the CPython
one. From v8.0.0, we "hide" the PyPy-only extension in a prefix before
the pointer we hand off to C-extension modules. The goal of this work is to
allow PyPy to use cp312-abi3 wheels produced for CPython 3.12 and up, using the
limited ABI. The required pieces have all been put in place:
PyPy's C headers, including struct definitions like
PyObject, are compatible with CPython's C headers when definingPy_LIMITED_API=0x030C0000PyPy no longer mangles exported function names from the limited API. In PyPy3.11 and earlier, functions like
PyTuple_Newwere exported asPyPyTupleNew.
Still missing: the import machinery must be taught that abi3.so shared objects are valid for PyPy, and the larger ecosystem (pip, uv) must also accept that cp312-abi3 wheels are valid candidates for installation.
Yes, this is a big step. We are working with Cython and PyO3 to make sure it all will Just Work™. Hopefully this will make it easier for packages to support PyPy.
What is new in RPython code generation
PyPy is written in RPython, and has code generation to translate RPython into C as part of the VM build process. We have made some improvements to code generation in attempts to speed up the base interpreter. While the speedups have not been that impressive, we have made some steps forward:
We now use computed gotos and more aggressively inline code. While this produces more compact sources, it does not boost performance as much as we wished.
The source code includes comments mapping the source back to the RPython code that generated the block. This is very helpful to see exactly what is going on, and may enable further improvements.
Dropping HPy
We have dropped the internal HPy backend for PyPy. The HPy project's understanding of how to use handles instead of pointers was a good prototype, but the project did not attract enough supporters to become a new standard. The code is still in the PyPy codebase, and can be toggled on with a build option.
A revived tool comparing headers and exported functions
We revived the clang-based pyhdrdump to compare PyPy's header files to CPython's header files. See the README for more information on how it works and how to use it.
Interpreters
The release includes three different interpreters:
PyPy2.7, supporting the syntax and the features of Python 2.7 including the stdlib for CPython 2.7.18+ (the
+is for backported security updates)PyPy3.11, supporting the syntax and the features of Python 3.11, including the stdlib for CPython 3.11.16. Barring security issues, this will be the last release to support 3.11.
PyPy3.12, supporting the syntax and features of Python 3.12, including the stdlib for CPython 3.12.14.
The interpreters are based on much the same codebase, thus the triple release.
We recommend updating. You can find links to download the releases here:
We would like to thank our donors for the continued support of the PyPy project. If PyPy is not quite good enough for your needs, we are available for direct consulting work. If PyPy is helping you out, we would love to hear about it and encourage submissions to our blog via a pull request to https://github.com/pypy/pypy.org
We would also like to thank our contributors and encourage new people to join the project. PyPy has many layers and we need help with all of them: bug fixes, PyPy and RPython documentation improvements, or general help with making RPython's JIT even better.
If you are a python library maintainer and use C-extensions, please consider making a CFFI version of your library that would be performant on PyPy. Failing that, PyPy will soon support the cp312-abi3 tag for limited ABI wheels. In any case, cibuildwheel supports building wheels for PyPy.
What is PyPy?
PyPy is a Python interpreter, a drop-in replacement for CPython. It's fast (PyPy and CPython performance comparison) due to its integrated tracing JIT compiler.
We also welcome developers of other dynamic languages to see what RPython can do for them.
We provide binary builds for:
x86 machines on most common operating systems (Linux 32/64 bits, Mac OS 64 bits, Windows 64 bits)
64-bit ARM machines running Linux (
aarch64) and macos (macos_arm64).
PyPy supports Windows 32-bit, Linux PPC64 big- and little-endian, Linux ARM 32 bit, RISC-V RV64IMAFD Linux, and s390x Linux but does not release binaries. Please reach out to us if you wish to sponsor binary releases for those platforms. Downstream packagers provide binary builds for debian, Fedora, conda, OpenBSD, FreeBSD, Gentoo, and more.
What else is new?
For more information about the 8.0.0 release, see the full changelog.
Please update, and continue to help us make pypy better.
Cheers, The PyPy Team
September 18, 2026 11:00 AM UTC
ListenData
AutoGPT : Everything You Need To Know
September 18, 2026 08:34 AM UTC
LernerPython blog, from Reuven Lerner
np.nan in Pandas: Why missing values break comparisons
Missing data in Python Pandas? We use nan (“not a number”), which comes from NumPy. np.nan is a float, but not a normal one:
The post np.nan in Pandas: Why missing values break comparisons appeared first on LernerPython.
September 18, 2026 06:00 AM UTC
Bob Belderbos
Protocol or ABC? Designing a pluggable provider interface
I was designing the provider boundary with a developer for a CLI tool that talks to two different image-generation backends.
Same inputs from the user, two different SDKs underneath. We were figuring out how best to define the shared contract: an abstract base class, or a typing.Protocol? This article has the answer.
