Planet Python
Last update: June 18, 2026 04:48 PM UTC
June 18, 2026
Ned Batchelder
Dodecahedron with stars
I saw this dodecahedron with an Islamic-inspired pattern designed by Taj Ragoo. As soon as I saw it, I knew I had to make one. I studied the pattern, wrote some Python, and made myself a PDF. I cut it out, folded it, glued it together, and now I have one of my own:

I love that this elegantly combines two pure geometric forms: the Platonic dodecahedron (12 uniform pentagons), and an Islamic pattern using five-pointed stars.
Looking closely, details emerge:

Each face has ten small stars in a ring. I’ve lightened them a bit in the front face here. At the center of each face is a ten-pointed star (highlighted in red), made of two overlaid five-pointed stars.
The real genius of the pattern is at the corners. I’ve highlighted one in blue. It’s a star made of the same parts as the central ten-pointed star, but there are only nine points. It works because three pentagons lying flat touching at a point occupy 324 degrees, leaving a 36-degree gap.
When the dodecahedron is folded together, the gap is closed. 36 degrees is exactly one-tenth of a complete 360-degree circle, so exactly one point of the ten-pointed star is missing, leaving a perfect nine-pointed star using the same shapes, spread over the corners of three pentagons. Beautiful!
If this appeals to you, follow Taj on Instagram: he’s got more Platonic/Islamic mashups to enjoy. The paper versions are just prototypes of the final versions he makes in wood.
Of course, you can get my PDF and make one for yourself:
The Python code to draw the net isn’t great: it has no real parallels to the structure of each face. It’s a lot of math and line drawing to get things in the right places. My ideal would be to have a toolset that used a tile-placing abstraction, to be able to do more interesting designs. Some day.
It was a joy to work on this though. It was a slow process of studying the original, working out the math, then mulling over coding approaches. The code was developed in small steps over weeks. Then printing initial versions, marking them up, working out the tab structure. Some copies were colored to understand how the lines flowed across the whole dodecahedron. It was good to be working in both the mental and physical worlds:

Python Software Foundation
PSF Board Election Dates for 2026
Python Software Foundation (PSF) Board elections are a chance for the community to choose representatives to help the PSF create a vision for and build the future of the Python community. This year, there are 4 seats open on the PSF Board. Check out who is currently on the PSF Board on our website. (Cheuk Ting Ho, Christopher Neugebauer, Denny Perez, and Georgi Ker are at the end of their current terms.)
The recent approval of the Packaging Council (PC) through PEP 772 means that the PC election will be held in parallel to the PSF Board election. For the first PC election, communications will be published on the PSF blog. Once the first PC has been established, they will define the standard lines of communication and more PC election process specifics for the future. More information on the PC election coming soon.
Board Election Timeline
- Nominations open: Tuesday, July 28th, 2:00 pm UTC
- Nomination cut-off: Tuesday, August 11th, 2:00 pm UTC
- Announce candidates: Thursday, August 13th
- Voter affirmation cut-off: Tuesday, August 25th, 2:00 pm UTC
- Voting start date: Tuesday, September 1st, 2:00 pm UTC
- Voting end date: Tuesday, September 15th, 2:00 pm UTC
Voting
You must be a Contributing, Supporting, or Fellow member by August 25th and affirm your intention to vote to participate in this election. Reminder: If you were formerly a Managing member, your membership type was changed to Contributing per 2024’s Bylaw change that merged Managing and Contributing memberships.
Check out the PSF membership page to learn more about membership classes and benefits. You can affirm your voting intention by following the steps in our video tutorial:
- Log in to psfmember.org
- Choose “Your Memberships” page at the top right to check your eligibility to vote (You must be a Contributing, Supporting, or Fellow member)
- Choose “Voting Affirmation” page at the top right
- Select your preferred intention for voting in 2026 (which now includes a second affirmation regarding your intention to vote in the PC election)
- Click the “Submit” button
Per another recent Bylaw change that allows for simplifying the voter affirmation process by treating past voting activity as intent to continue voting, if you voted last year, you will automatically be added to the 2026 voter roll. Please note that if you removed or changed your email on psfmember.org, you may not automatically be added to this year's voter roll.
If you have questions about membership, please email psf-elections@pyfound.org.
Election communications from psfmember.org
PSF Members should review their communication preferences on psfmember.org if you would like to opt in or out of receiving emails about either the PSF Board, PC elections, or both. Here’s how:
- Login to https://psfmember.org/
- Navigate to your “Profile” page
- Click the “Name and Address” tab
- Scroll down, designate your preferences
- Click submit
If you had previously opted out of communications from the PSF through psfmember.org and would like to start receiving them, we encourage you to update them using the instructions above. If you're not sure what how your psfmember.org communication preferences are currently set, you can check via the "Name and Address" tab mentioned above, and make any adjustments as desired.
The PSF only sends a handful of election and fundraising related communications every year via psfmember.org. The PSF newsletter runs through a separate mailing list (and we heartily welcome you to sign up for our newsletter!).
Run for the Board
Who runs for the board? People who care about the Python community, who want to see it flourish and grow, and also have a few hours a month to attend regular meetings, serve on committees, participate in conversations, and promote the Python community. We're looking for candidates with a diverse range of skills and backgrounds, including leadership experience, fundraising knowledge, non-profit familiarity, and event organizing. Technical expertise, a record of collaboration, and experience speaking or teaching in the Python community are also all qualities we hope to see in Board members.
Want to learn more about being on the PSF Board? Check out the following resources to learn more about the PSF, as well as what being a part of the PSF Board entails:
- Life as Python Software Foundation Director video on YouTube
- FAQs About the PSF Board video on YouTube
- Our past few Annual Impact Reports:
You can nominate yourself or someone else. If you're nominating someone else, we'd encourage you to reach out to them first to make sure they're excited about the opportunity and give them a heads up that they'll need to submit their own nomination statement too. Nominations open on Tuesday, July 28th, 2:00 pm UTC, so you have time to talk with potential nominees, research the role, and craft a nomination statement for yourself or others. Take a look at last year’s nomination statements for reference.
Learn more and join the discussion
You are welcome to join the discussion about the PSF Board election on our forum. This year, we’ll also be hosting PSF Board Office Hours on the PSF Discord in July and August to answer questions about running for and serving on the board. Subscribe to the PSF blog or, if you’re a member, join the psf-member-announce mailing list to receive updates leading up to the election.
Bob Belderbos
When to use classmethod, staticmethod, or instance method in Python
In a coaching call this week we discussed a create classmethod, and someone asked the obvious question: why is that here? It just forwarded its arguments to __init__. We ended up discussing the difference between instance methods, classmethods, and staticmethods, and how to tell which is which. Here's a simple decision rule.
The decision rule
Look at what the method actually touches:
- Needs the instance (
self) → instance method - Needs the class (
cls) but not a specific instance →@classmethod - Needs neither →
@staticmethod
Nice, but what are some actual use cases? Let's look at the create method that prompted the question.
The create method from the call fails the rule above. It took the same arguments as __init__ and passed them straight through. It still adds a nice interface (Class.create(...)), but it doesn't do any work that the constructor doesn't already do:
# shortened for clarity
@classmethod
def create(cls, amount: Decimal, currency: Currency = Currency.EUR) -> "Expense":
return cls(amount=amount, currency=currency)When a classmethod earns its place
A classmethod pulls its weight when it does work the constructor shouldn't, or builds the object from a different starting point. Add a normalization step and the same method suddenly has a job:
@classmethod
def create(cls, amount: Decimal, currency: Currency = Currency.EUR) -> "Expense":
return cls(amount=amount.quantize(Decimal("0.01")), currency=currency)
The canonical use of a @classmethod is the alternative constructor. Python won't let you overload __init__, so when you want to build an object several ways, each way becomes a classmethod.
The standard library has rich examples, for example take a look at datetime.date:
date.today() # from the system clock
date.fromtimestamp(1718539200) # from a POSIX timestamp
date.fromisoformat("2026-06-16") # from an ISO 8601 string
date.fromordinal(739418) # from a proleptic Gregorian ordinal
date.fromisocalendar(2026, 25, 1) # from ISO year/week/day
Source:
# Additional constructors
@classmethod
def fromtimestamp(cls, t):
"Construct a date from a POSIX timestamp (like time.time())."
if t is None:
raise TypeError("'NoneType' object cannot be interpreted as an integer")
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
return cls(y, m, d)
@classmethod
def today(cls):
"Construct a date from time.time()."
t = _time.time()
return cls.fromtimestamp(t)
...
...
Every one of those returns a date, but starts from different raw material. They have to be classmethods because they need cls to construct the instance, and they return cls(...) which makes it also work with subclasses. For instance, if MyDate subclasses date, then MyDate.today() will return a MyDate instance, not a date.
Bonus: I was annoyed that my pysource package didn't work, so I've since patched it, and now you can get to this source code easily with:
uvx --from pybites-pysource pysource -m datetime.date
(I tend to pip this into Vim with | vi - to read the source code in a scratch buffer.)
You'll see the same pattern across the ecosystem: dict.fromkeys(...), int.from_bytes(...), and in Pydantic Model.model_validate(...) / model_validate_json(...) are all classmethods that build an instance from different raw material.
Another classmethod use case is class-level state: registries, caches, counters. A plugin registry is the clean example, because the method reads and mutates state that belongs to the class, not to any instance:
class Handler:
_registry: dict[str, type["Handler"]] = {}
@classmethod
def register(cls, name: str, handler: type["Handler"]) -> None:
cls._registry[name] = handler
@classmethod
def get(cls, name: str) -> type["Handler"]:
return cls._registry[name]
# called on the class, no instance needed; it mutates state that lives on the class
Handler.register("json", JSONHandler)When it's really a staticmethod
If the method touches neither self nor cls, it's a staticmethod, which is a plain function that happens to live inside the class for namespacing. That's a legitimate choice when the helper is tightly bound to the class and you want Expense.normalize(...) to read well. It's now part of the class API (it shows up in dir(Expense)) and can be called without an instance.
Genuine staticmethods are rarer than the other two, which itself tells you something. A clean example is a Color class with conversion helpers (from a Pybites exercise):
class Color:
def __init__(self, name: str):
self.name = name
self.rgb = COLOR_NAMES.get(name.upper())
@staticmethod
def hex2rgb(hex_value: str) -> tuple[int, int, int]:
return tuple(int(hex_value[i:i + 2], 16) for i in (1, 3, 5))
@staticmethod
def rgb2hex(rgb: tuple[int, int, int]) -> str:
return f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}"
hex2rgb and rgb2hex touch neither the instance nor the class. They're pure conversions that live on Color so Color.hex2rgb("#ff0000") reads well next to the rest of the API.
But that's exactly the signal worth noticing: a staticmethod might be just a function in disguise, and sometimes the honest move is to pull it out to a module-level function where it's easier to test and use on its own.
Summary
| Method type | First argument | Access to | Common use case |
|---|---|---|---|
| Instance method | self | Instance & class state | Modifying object state |
Class method (@classmethod) | cls | Class state only | Alternative constructors, registries |
Static method (@staticmethod) | none | Neither | Isolated utility/helper functions |
Why this matters more now
When you write the code yourself, you rarely add a method without a reason. When an agent writes it, you get plausible-looking structure that nobody chose. A create classmethod that does nothing, a staticmethod that should be a free function, a helper hanging off the wrong class. That's your judgment call: is this method doing work that belongs to the class, or is it just a pattern the agent learned from other code?
It pays to slow down and look critically at any code and ask those questions. With AI producing more code faster, it's easy to assume that if it looks like Python, it's good Python. But the agent has no taste, and it will happily produce code that is technically correct but structurally wrong.
This is also why I keep writing articles like this one: to give you a simple decision rule you can run in your head during review. It reminds me of Rust, which makes data flow explicit right in the signature with self, &self, and &mut self. The signature tells you what the method touches, same idea as the rule here. (That data-and-behavior split is the whole theme of Why Rust does not need OOP.)
So use AI, but keep developing your knowledge and taste. The more you know, the better you judge the code that comes your way, whether a human or an agent wrote it.
June 17, 2026
PyCharm
Every developer has tools they rely on daily. The workflows they’ve built around them, the ways they’ve learned to move faster, debug smarter, and write better code – that kind of hands-on experience can be hard to put into words.
We’re collaborating with LinkedIn to make it easier for you to showcase your expertise with JetBrains IDEs on the world’s largest professional network. You can now connect your IDE to LinkedIn and let your real tool usage speak for itself.
IntelliJ IDEA, PyCharm, WebStorm, PhpStorm, Rider, GoLand, CLion, RustRover, and RubyMine are already supported via a free plugin, while support for DataGrip is coming soon.
In this blog post, we’ll explain what LinkedIn connected apps are, what they mean for your profile, and how to get started.
What this is about
Building on early collaboration with Descript, Duolingo, Lovable, Relay.app, and Replit, LinkedIn is expanding the range of apps you can feature on your LinkedIn profile, turning real-world product usage into a credible, visible signal of practical tool experience. We’re glad to join forces with them to bring this to JetBrains IDE users.
“We’re building new ways for members to show real, credible proof of what they’re capable of, right on their LinkedIn profile. And for the brands behind these tools, there’s no better endorsement than a customer who’s actively using and loving your product.”
– Dan Shapero, CEO of LinkedIn
Connected apps let you link the tools you use in your daily work directly to your LinkedIn profile, where they appear prominently, helping you stand out to your professional network. Once connected, each app generates a simple statement based on how you actually use it. Unlike manually added skills, this is based on real usage and updates automatically as your experience evolves.
How to get started
Open your JetBrains IDE, go to Settings | Plugins, search for the LinkedIn Connected Apps plugin under the Marketplace tab, and install it.
Once installed, the plugin starts collecting data locally about how you use your IDE. Depending on your usage history, you may receive an initial statement right away, which will then be updated once the plugin has collected enough data to better reflect your real IDE expertise.
Your IDE usage data stays on your machine. When you are ready, you can connect your LinkedIn account and share your IDE expertise badge there. If you keep the plugin installed, your badge will update automatically as your IDE usage evolves.
The plugin is free for all JetBrains IDE users.
What’s included in this release
This is the first version of the integration, delivered as a standalone plugin rather than being built directly into the IDE. It covers IntelliJ IDEA, PyCharm, WebStorm, GoLand, PhpStorm, Rider, CLion, RustRover, and RubyMine; DataGrip is not yet supported.
Usage is detected within the IDE itself, so if you use AI features via an external tool or terminal, those won’t be reflected yet.
How your IDE expertise is determined
The model is intentionally simple for now. It is designed to represent your practical use of JetBrains tools, not to rank developers or certify skill levels. Our goal was to provide a solid starting point, but we know there’s more to capture about how developers work with their IDEs.
Statements map to different levels of experience and are generated based on how you interact with your IDE – from writing and editing code using basic features to working with debugging tools, version control, and AI-assisted workflows. For more information, see our documentation.
What’s coming next
We’re already working on the next version, planned for later this year. We’ll focus on improving how IDE usage, including AI feature usage, is represented, expanding support to DataGrip, and making the overall experience feel more integrated.
FAQ
Which JetBrains IDEs are supported?
IntelliJ IDEA, PyCharm, WebStorm, GoLand, PhpStorm, Rider, CLion, RustRover, and RubyMine. Support for DataGrip is coming soon.
Why isn’t DataGrip supported yet?
DataGrip is designed for working with databases and includes workflows that differ from our other IDEs. We plan to support it soon.
Can I connect multiple IDEs?
Yes, if you use multiple supported JetBrains IDEs, you can connect each of them. You’ll get a badge for all connected IDEs.
Note: If you use multiple JetBrains accounts across different IDE instances but link them all to the same LinkedIn profile, IDE usage statements from each account will be displayed on that LinkedIn profile.
Do I need to keep the plugin installed after connecting?
You can share your IDE usage statement once and then remove the plugin, but note that it must remain installed if you want to track your ongoing progress and have any changes reflected on LinkedIn.
Is this feature free?
Yes, it’s available to all JetBrains IDE users at no cost.
Is this a certification?
Connected apps reflect real IDE usage and are designed to showcase applied experience, not to act as a formal certification or skill ranking. Certifications, degrees, and licenses remain important markers of professional achievement. Connected apps on LinkedIn add a different kind of signal: partner-validated tool usage that reflects practical work and can update over time.
What data is shared with LinkedIn and JetBrains?
Only the information required to represent your connected account and IDE usage statement.
Will this help me get hired?
Having connected apps on your LinkedIn profile is extra proof of your practical experience with leading tools. While connected apps make your expertise visible, they are just one part of your profile. Think of it as a way to let your tooling speak for itself.
Give it a try and let us know what you think in the comments below. We’re continuing to develop this integration, and your feedback will help shape what comes next.
Talk Python to Me
#552: Astral joins OpenAI
OpenAI just acquired Astral, the company behind uv, Ruff, and ty. And if your first thought was "wait, is uv toast?", you are not alone. But here's the twist Charlie Marsh shared with me: he thinks they may ship more open source at OpenAI than they ever did at Astral. On this episode, we get into the acquisition, the mixed feelings, the future of your favorite Python tools, and what it's like to build right at the center of the AI universe.<br/> <br/> <strong>Episode sponsors</strong><br/> <br/> <a href='https://talkpython.fm/sentry'>Sentry Error Monitoring, Code talkpython26</a><br> <a href='https://talkpython.fm/training'>Talk Python Courses</a><br/> <br/> <h2 class="links-heading mb-4">Links from the show</h2> <div><strong>Guest</strong><br/> <strong>Charlie Marsh</strong>: <a href="https://github.com/charliermarsh?featured_on=talkpython" target="_blank" >github.com</a><br/> <br/> <strong>The announcement</strong>: <a href="https://astral.sh/blog/openai?featured_on=talkpython" target="_blank" >astral.sh</a><br/> <strong>OpenAI</strong>: <a href="https://openai.com/?featured_on=talkpython" target="_blank" >openai.com</a><br/> <strong>uv</strong>: <a href="https://github.com/astral-sh/uv?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>ty</strong>: <a href="https://github.com/astral-sh/ty?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>Ruff</strong>: <a href="https://github.com/astral-sh/ruff?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>pyx</strong>: <a href="https://astral.sh/pyx?featured_on=talkpython" target="_blank" >astral.sh</a><br/> <strong>Codex team</strong>: <a href="https://openai.com/codex/?featured_on=talkpython" target="_blank" >openai.com</a><br/> <strong>Anthropic did something similar by acquiring Bun</strong>: <a href="https://www.anthropic.com/news/anthropic-acquires-bun-as-claude-code-reaches-usd1b-milestone?featured_on=talkpython" target="_blank" >www.anthropic.com</a><br/> <strong>Daily Stars Explorer</strong>: <a href="https://emanuelef.github.io/daily-stars-explorer/#/astral-sh/uv" target="_blank" >emanuelef.github.io</a><br/> <br/> <strong>Agentic AI Programming for Python</strong>: <a href="https://training.talkpython.fm/courses/agentic-ai-programming-for-python" target="_blank" >training.talkpython.fm</a><br/> <strong>Python Web Security: OWASP Top 10 with Agentic AI</strong>: <a href="https://training.talkpython.fm/courses/agentic-ai-python-security" target="_blank" >training.talkpython.fm</a><br/> <br/> <strong>Episode #552 deep-dive</strong>: <a href="https://talkpython.fm/episodes/show/552/astral-joins-openai#takeaways-anchor" target="_blank" >talkpython.fm/552</a><br/> <strong>Episode transcripts</strong>: <a href="https://talkpython.fm/episodes/transcript/552/astral-joins-openai" target="_blank" >talkpython.fm</a><br/> <br/> <strong>Theme Song: Developer Rap</strong><br/> <strong>🥁 Served in a Flask 🎸</strong>: <a href="https://talkpython.fm/flasksong" target="_blank" >talkpython.fm/flasksong</a><br/> <br/> <strong>---== Don't be a stranger ==---</strong><br/> <strong>YouTube</strong>: <a href="https://talkpython.fm/youtube" target="_blank" ><i class="fa-brands fa-youtube"></i> youtube.com/@talkpython</a><br/> <br/> <strong>Bluesky</strong>: <a href="https://bsky.app/profile/talkpython.fm" target="_blank" >@talkpython.fm</a><br/> <strong>Mastodon</strong>: <a href="https://fosstodon.org/web/@talkpython" target="_blank" ><i class="fa-brands fa-mastodon"></i> @talkpython@fosstodon.org</a><br/> <strong>X.com</strong>: <a href="https://x.com/talkpython" target="_blank" ><i class="fa-brands fa-twitter"></i> @talkpython</a><br/> <br/> <strong>Michael on Bluesky</strong>: <a href="https://bsky.app/profile/mkennedy.codes?featured_on=talkpython" target="_blank" >@mkennedy.codes</a><br/> <strong>Michael on Mastodon</strong>: <a href="https://fosstodon.org/web/@mkennedy" target="_blank" ><i class="fa-brands fa-mastodon"></i> @mkennedy@fosstodon.org</a><br/> <strong>Michael on X.com</strong>: <a href="https://x.com/mkennedy?featured_on=talkpython" target="_blank" ><i class="fa-brands fa-twitter"></i> @mkennedy</a><br/></div>
PyCharm
Your JetBrains IDE Expertise, Now on LinkedIn
Django Weblog
Announcing the Search for a DSF Executive Director
The Django Software Foundation is hiring its first Executive Director, and we have the Django community to thank for making it possible.
Six Django web development agencies have jointly pledged $47,500 to help fund the Executive Director's first year: Caktus Group, Lincoln Loop, Six Feet Up, Cuttlesoft, OddBird, and Two Rock. This is the financial foundation we needed to move from "we should hire an ED someday" to "we are hiring an ED now."
Why This Role Matters
The DSF has grown significantly over the past several years. We fund multiple Django Fellows, distribute grants to events around the world, manage corporate and individual memberships, oversee working groups, and handle the legal and operational responsibilities of a 501(c)(3) nonprofit. For years, volunteer board members have carried this operational load alongside their regular jobs. That dedication has carried us far, but there are real limits to what a volunteer board can do.
An Executive Director changes that. This person would handle day-to-day operations and administration, sponsorship development and partner relationships, community outreach and communications, coordination with the Django Fellows and working groups, and grant management and financial reporting.
It is a paid position, part-time or full-time depending on the candidate, for someone who understands open source communities and is genuinely excited about helping Django thrive as both a framework and a foundation.
"For years our board has run the DSF on volunteer time, and we've hit the limits of what that can do. An Executive Director lets us actually grow the work, more support for Django Fellows, better fundraising, and the operational help we've needed for a long time," said Jeff Triplett, DSF Board President. "We've talked about this hire for years, and funding was always what held us back. Six agencies who compete with each other decided to put money in together so we could finally do it. That tells you how much this community cares about Django's future."
The Agencies Who Made This Possible
These six agencies compete for the same clients, but they share a foundation: Django. That shared reliance drove them to collaborate on this pledge, and we want to recognize each of them.
Caktus Group ($12,500), the Durham, NC consultancy founded in 2007 and known for data-intensive Django work with clients like UNICEF and the University of Chicago, put it directly. CEO Tobias McNulty said: "Django is the bedrock of our business, and as a smaller team, contributing is a significant investment. We hope this coordinated action from six agencies sends a clear signal to the rest of the industry: it's time to contribute to the core technology that makes our businesses possible."
Lincoln Loop ($10,000), the remote-first Python consultancy that has built platforms for Planned Parenthood, Wharton, Mozilla, and PBS, framed it as a question of sustainability. Founder Peter Baumgartner said: "We've seen the Django community thrive under volunteer leadership, but we've reached a ceiling. The Executive Director role is about sustainability, providing the leadership and structure needed to scale the DSF's impact and protect Django's long-term future."
Six Feet Up ($10,000), the woman-owned consultancy founded in 1999 with clients including Capital One, Purdue University, and UNEP, focused on what this means for enterprise confidence in Django. CEO Gabrielle Hendryx-Parker said: "Tech leaders stake their roadmaps on the long-term viability of their technology stack. A full-time Executive Director de-risks the framework's future, protecting the robust and lasting systems we build for our clients and ensuring Django remains a bankable, innovative choice."
Cuttlesoft ($10,000), the product agency based in Tallahassee and Denver that has been building with Django since 2014, sees the hire as an investment in the whole ecosystem. Co-founder Frank Valcarcel said: "Investing in a dedicated Executive Director is a proactive step toward ensuring Django's continued evolution. We believe this role will unlock new opportunities for growth and collaboration within the community, benefiting all who rely on this incredible framework."
OddBird ($2,500), the remote boutique agency co-founded by Django core developer Jonny Gerig Meyer, has been contributing to both the framework and the community for more than 17 years. Jonny said: "Adding a dedicated Executive Director helps the DSF ensure Django's long-term sustainability, giving developers and enterprise clients peace of mind choosing the Django ecosystem. This investment is a no-brainer, and we're thrilled to partner with other peer agencies to help make it a reality."
Two Rock Software ($2,500), the Django-focused custom development shop with deep roots in the Django events community, rounded out the pledge. Co-founder Peter Grandstaff, who serves as President of Django Events Foundation North America and helps run DjangoCon US, said: "As President of Django Events Foundation North America, I know how hard it is for a volunteer board to run an effective organization. I feel strongly that Django is at a point where an Executive Director is the right step into the future."
We Need Your Help Too
This $47,500 pledge is a launchpad, not the finish line.
Hiring an Executive Director means taking on a recurring cost that our current fundraising levels cannot sustain on their own. That is why the DSF is raising its annual fundraising goal from $300,000 to $500,000 (2026 fundraising goals). The additional funding reflects what it takes to responsibly hire and maintain this role, continue supporting our Django Fellows, and keep the rest of our programs running without cutting corners.
Six agencies stepped up first. We are asking others to follow.
If your company builds on Django, sells products that run on Django, or employs developers who work with Django every day, this is your opportunity to invest in the infrastructure that makes that possible. No contribution is too small, and every organization that joins this effort makes it easier for the next one to say yes.
You can reach out directly through our Contact the DSF page to discuss a contribution toward the Executive Director fund, or make a general donation at djangoproject.com/foundation/donate/. Individual community members can also contribute via Open Collective.
With the community's help, with your company's help, we can get there.
What Comes Next
The board is formalizing the hiring process and will publish the job posting in the coming weeks. When it is ready, we will announce it across the DSF blog, Django Forum, Django Discord, and our other community channels.
If you know someone who would be a great fit for this role, start thinking about them now.
Thank you to Caktus Group, Lincoln Loop, Six Feet Up, Cuttlesoft, OddBird, and Two Rock for leading the way.
Python Software Foundation
Everything Security at PyCon US 2026
Phew, PyCon US 2026 is a wrap! Now it's time to share about everything security that happened in case you weren't able to attend (or you just want to reminisce). Subscribe to the PyCon US channel on YouTube so you're notified as soon as recordings for each talk are published. This blog post will also be updated with links once all talks are available.
![]() |
| Hala Ali on generating SBOMs directly from the Python runtime |
Juanita Gomez and Seth Larson were the chairs of the first talk track dedicated to security at PyCon US: Trailblazing Python Security! We're excited to share the recordings for each talk featured in the track:
- Anatomy of a Phishing Campaign by Mike Fiedler
- Zero Trust in 200ms: Implementing Identity-Per-Transaction with Python and Serverless by Tristian McKinnon
- Rust for CPython by Emma Smith
- Asleep at the Wheel: SBOMit for Python builds by Sanchit Sahay and Abhishek Reddypalle
- Post-Incident Runtime SBOM Generation from Python memory by Hala Ali
- GitHub Actions Security in Python Packages by Andrew Nesbitt
- Breaking Bad (Packages): Why Traditional Vulnerability Tracking Fails Supply Chain Attacks by Shelby Cunningham and Madison Ficorilli
Thanks so much to the speakers and volunteers who helped make this inaugural track a success. For several of the talks above the room was standing-room only! The support and interest in security topics from the Python community was incredible to see and we're hoping to see you all again next year to continue learning and sharing ideas.
| "Security isn't free!" |
Following Amanda Casari's amazing keynote, Mike Fiedler and Seth Larson took the stage to give a brief update of the past year of security work at the Python Software Foundation (PSF).
Overall 2026 was the year of more, both good and not-so-good. More packages than ever and being published to the Python Package Index (PyPI), but also more malware and specifically watering-hole attacks targeting PyPI users. The double-edged sword of being a popular and widely-used programming language also makes Python and its users a more interesting target for attackers.
The slides for this presentation are available for download via speakerdeck.
For the fourth year in a row Seth Larson hosted a security-themed Open Space at PyCon US. This year the open space was titled "Security for Open Source project maintainers" with the goal of "gather with fellow open source project maintainers to discuss current challenges with open source security".
A handful of Open Source maintainers were present to discuss security issues. The format was open-ended discussion with a few prompts to start the discussion off including vulnerability handling and CI/CD security.
Following the many watering-hole attacks on established Open Source projects involving CI/CD pipelines, hardening project CI/CD pipeline definitions was the first discussion topic. The overwhelming recommendation was to use Zizmor
with its --fix mode and a GH_TOKEN. Other tools came up such as gha-update,
pinact, Dependabot, Renovate, and using lock files like pip-compile to lock
dependencies in your CI/CD workflows. Dependency Cooldowns were also a popular concept for dependencies involved in builds and publishing.
The most recent resource published for all-in-one repository security was a blog post by William Woodruff on open source security at Astral that details CI/CD security and how to configure repositories.
The bulk of the discussion was about vulnerabilities and challenges around handling the volume of reports from reporters using LLMs. The prevailing theme is that the volume of reports has increased substantially, with anec-data being that vulnerability handling "previously was ~20% of time spent on a project" and is now "almost all" the time spent. Many reports are duplicates, verbose, extremely low quality due to the use of LLMs but the number of valid or almost-security issues has increased, too.
This "almost all" number is particularly frightening, many Open Source contributors didn't get into this line of volunteering because they wanted to work on security-related tasks.
There was some side discussion about how to judge whether handling a vulnerability in private was still a useful thing to do if the vulnerability is trivially discoverable using a publicly available LLM. The conversation referenced the Linux kernel's discussion of the same topic.
Talking about ways to mitigate the negative effects of LLMs and agents on security work lead to a discussion of security policies and threat models. Few projects, especially smaller ones, have tried this approach of documenting their threat model to see if this has a meaningful impact on the quality or quantity of reports received.
Python, Django, Node, and curl were given as good examples of threat models to copy and learn from for your own projects.
There was an issue of discoverability, some documentation is
in CONTRIBUTING.md, or on a website, but not checked into
source control for the actual project, or used an organization-wide
.github/SECURITY.md. Some projects didn't use an AGENTS.md (and
didn't want to, for fear of inviting even more LLM-driven contributions), and it was difficult to tell whether any particular documentation was
having an effect. There's also the difficulty of models changing or
becoming more capable over time. More testing is necessary here!
A separate meta-conversation through the previous topics was about having a way to signal that a particular contributor or security researcher had a high "contributor quality". The value of such a signal would tell maintainers where to focus their limited time, such as reports from someone more likely to engage with the process and follow instructions. "Talking with an LLM, indirectly" was mentioned multiple times as a negative but unfortunately common experience of maintainers interacting with first-time contributors.
gh-profiler from Eric Matthes was referenced during the discussion, and a few maintainers tested this on their own profiles and profiles of low-quality contributions they'd received recently. There was an interest in finding metrics or signals that are tougher to automate or fake. The group identified that as soon as such a signal was widely used that agents would simply "route around" the barrier.
Alpha-Omega × Python Software Foundation
Thanks to Alpha-Omega for sponsoring security at the PSF. Their support funds two roles: the Security Developer-in-Residence, held by Seth Larson, and the PyPI Safety & Security Engineer, held by Mike Fiedler. Seth and Mike delivered a joint update on their work at PyCon US 2026.
The over-arching theme of the update was the impact of higher volumes of reports, vulnerabilities, malware, and supply-chain attacks are having on the Python ecosystem along with work done to mitigate some of the hockey-stick graphs we're seeing.
Seth detailed the Python Security Response Team (PSRT) governance and process changes detailed in PEP 811. These changes aim to improve the capacity of the PSRT ahead of an increasing workload triaging and remediating security vulnerabilities reported to Python and pip.
Mike detailed work for mitigating malware and supply-chain attacks to PyPI, especially novel attacks such as the Shai-Hulud worm that targets and exploits insecure CI/CD pipelines and developer API tokens to propagate malware.
If you are interested the full set of slides is available for download via speakerdeck.
Bob Belderbos
Building an AI Agent in 6 Weeks (and Finally Understanding How They Work)
Jeff Haemer has written software since he was teaching it at the University of Colorado in the early 1980s. But he felt he needed to brush up his Python, and above all get a grounding in AI.
In his words AI was "a big undifferentiated cloud of things I didn't know." Time to change that.
Six weeks into our Python Agentic AI cohort, he ended up with an agentic application with a few thousand lines of code, almost 250 unit tests, 100% coverage, and three working interfaces: a web UI, a command line, and a Telegram bot that talks to his phone.
He even went as far as running mutation testing. More than that, through the program he developed a mental model of how agents actually work under the covers.
The gap
Jeff came in with a long career behind him and a clear-eyed view of what he was missing:
"It's a giant world and changing every day, and I didn't even know in many ways where to start. When you told me you were thinking about doing an AI cohort, I said, please do that and sign me up, and I will happily jump in feet first."
He set expectations low on purpose. "I expected myself to crash and burn because I have a very spotty background." He'd taught plenty of courses; he knew how the first run of anything goes. He signed on as the cohort's beta tester and decided to stay enthusiastic through whatever broke.
Watch the full interview with Jeff:
Core logic first, interfaces on top
An agent is a program that takes a request, reasons about it with an AI model, and acts. The cohort builds the reasoning core first, then wraps interfaces around it. That structure got tested the hard way in the Telegram week, when connecting the agent to a chat app hit a wall.
"I got to the end of that week and I wasn't even close, and I said, okay, I failed you. And you said, go on to the next week, because we designed the software so those units are independent of one another. We'll rewrite it."
He moved on. The Telegram unit was independent, so an unfinished interface didn't block the rest of the build. We later rebuilt that week's material from almost 100 pages down to 41, starting from a simpler working version. When Jeff came back to it, it worked.
"It was beautiful. When we hit a speed bump, that worked. It proved itself."
There's a meta lesson here, and a reminder of what well-designed software looks like: build the thing that does the work first, keep the edges replaceable. This saved the beta cohort from going under.
Mocking, the thing he kept putting off
The concept that gave Jeff the most trouble was mocking, the practice of replacing a real outside service (an API, a database) with a stand-in so a test can run fast and offline.
"The biggest pain for me was finally understanding what mocking involves. I even asked a friend of mine, a test automation Python guy, and he said, I never really understood that either."
He avoided it until week four or five, when Juanjo made it non-negotiable:
"You got me to the point where I could actually separate my unit tests, which were independent of outside services, from my integration tests. I learned stuff about pytest, I learned stuff about mocking, and I learned stuff about my own code. I just ended up thinking about things in a different way."
Jeff's rigor with the test suite paid dividends. By the end they were catching real issues, including a function that slipped coverage when he deployed to a Debian box, which he set out to track down on his own.
AI as teaching assistant, not autopilot
Jeff wrote the code by hand. He used AI deliberately, as a tutor for the spots where his Python ran out, not as a generator to fill the file for him.
"I understand conceptually what to do here, but I don't know enough Python to struggle through the docs and work through all the bugs in that short amount of time. So, show me how to do this. AI turns into a great teaching assistant."
Unit tests gave each week a definition of done. The result is an artifact he can reason about, not a diff he has to trust on faith.
Understanding by building
The win Jeff cared about most wasn't the repo. It was the mental model:
"It's different having done it than even reading about it. If somebody had written an explanation, a week later I'd have a vague idea, a month later I'd say I read an article about it but don't remember anything, and two months later I'd say I've never heard of that. This, I think I understand."
He tested it against a toy agent he found in the wild, a hallucinating Wikipedia clone, and could trace exactly what it did: validate the input, structure it, hand it to the model, get structured output back, cache it in a database.
From "big undifferentiated cloud of things I didn't know" to a firm grounding in how AI agents work. Jeff ended up with a great artifact on GitHub, but the real win has been this deeper understanding that he will take to his next AI project.
We're excited to see what Jeff will build next with this new skill set.
June 16, 2026
PyCoder’s Weekly
Issue #739: JIT Delayed, Sandboxes, OpenRouter, and More (2026-06-16)
#739 – JUNE 16, 2026
View in Browser »
Steering Council Announcement Regarding the JIT
The Python Steering Council has announced that the work on the JIT needs to be paused until a new PEP gets written. There are many unresolved questions about the approach and integration with other tools and the work on the JIT has reached a stage where these questions need to be answered. Additional discussion
PYTHON.ORG
Python in a Sandbox With MicroPython and WASM
Simon’s been in search of the perfect code sandbox. This article is about his latest attempt and covers why he wants a sandbox and what tech he’s used to achieve it.
SIMON WILLISON
Wallaby for Python runs Tests as you Type and Streams Results Next to Code, Plus AI Context
Wallaby brings pytest / unittest results, runtime values, coverage, errors, and time-travel debugging into VS Code, so you can fix Python faster and give Copilot, Cursor, or Claude the execution context they need to stop guessing. Try it free, now in beta →
WALLABY sponsor
Accessing Multiple AI Models With the OpenRouter API
Access models from popular AI providers in Python through OpenRouter’s unified API with smart routing, fallbacks, and cost controls.
REAL PYTHON course
Articles & Tutorials
Skip Jupyter’s Hidden State: Reactive Notebooks With Marimo
Marimo is a reactive Python notebook designed to make data science workflows more reproducible. This article shows how it avoids hidden execution state, saves notebooks as plain .py files for cleaner Git diffs, isolates dependencies with uv, supports pytest cells, and exports notebooks into reusable formats including scripts, HTML, and WASM dashboards.
CODECUT.AI • Shared by Khuyen Tran
EuroPython 2026: Celebrating 25 Years
What’s happening at EuroPython 2026? The conference celebrates its 25th anniversary this year in Kraków, Poland. This week on the show, organizers Mia Bajić and Daria Linhart Grudzien join me to discuss this year’s conference.
REAL PYTHON podcast
SQLPyHelper: Unified DataBase API
SQLPyHelper is a Python library that provides a unified API across SQLite, PostgreSQL, MySQL, SQL Server, and Oracle. It has async support for FastAPI, cross-database migration, connection pooling, and transactions.
DEV.TO • Shared by Adebayo Olaonipekun
Stroll Down Startup Lane
PyCon’s Startup Row is a stretch of booths where early-stage companies built on Python show off what they’re creating. In this episode, Talk Python interviews a host of folks from this year’s booths.
TALK PYTHON podcast
Pyodide 314.0 Release
This post announces the Pyodide 314.0 release and describes its features, including a focus on standardization and packaging. You can now build Pyodide wheels and post them to PyPI.
PYODIDE.ORG
The Smallest Brain You Can Build
A perceptron explained from scratch in Python, with interactive demos. Learn weights, bias, the decision boundary, epochs, learning rate, and why you normalize data.
DEVARSH RANPARA
Are You Expected to Run 5 Type-Checkers Now?
Library maintainers may feel overwhelmed by the plurality of type checkers that exist. We offer some guidance on how to focus their efforts where they matter most.
MARCO GORELLI
How to Tell if Your Python Mock Is Actually Working
A test that passes because the real API returned an error is not a passing test. Here’s how to verify your mock is intercepting, and fix it when it isn’t.
BOB BELDERBOS
Cursor vs Windsurf: Which AI Code Editor Is Best for Python?
Compare Cursor vs Windsurf for Python across code completion, multi-file editing, and debugging to choose the right editor for your workflow.
REAL PYTHON
Tricky Python Quiz
A tricky Python quiz game about surprising edge cases, weird outputs, and traps with questions from the popular WTFPython GitHub repo.
ADARSHD.DEV • Shared by Adarsh Divakaran
Free Threading Internals: Deferred Reference Counting
This is a follow up to Victor’s article on reference counting covering more complex counting mechanisms including immortal objects.
VICTOR STINNER
Projects & Code
uuid-utils: Rust-Based Replacement for Python’s UUID
GITHUB.COM/AMINALAEE • Shared by Amin
django-deploy-probes: Django Health & Startup Endpoints
GITHUB.COM/EMFPDLZJ • Shared by minjeong bak
NumCircBuf: High-Performance Numerical Circular Buffers
GITHUB.COM/BASIMALI-AI • Shared by Syed Basim Ali
Events
Weekly Real Python Office Hours Q&A (Virtual)
June 17, 2026
REALPYTHON.COM
PyData Bristol Meetup
June 18, 2026
MEETUP.COM
PyLadies Dublin
June 18, 2026
PYLADIES.COM
Python for (Almost) Everything
June 18 to June 19, 2026
MEETUP.COM
PyCon Singapore 2026
June 19 to June 22, 2026
PYCON.SG
Happy Pythoning!
This was PyCoder’s Weekly Issue #739.
View in Browser »
[ Subscribe to 🐍 PyCoder’s Weekly 💌 – Get the best Python news, articles, and tutorials delivered to your inbox once a week >> Click here to learn more ]
Ari Lamstein
Upcoming O’Reilly Workshop: Building Data Apps with Streamlit and Copilot (July 2026)
On July 9 (9am–1pm Pacific), I’ll be teaching a 4‑hour live workshop for O’Reilly: Building Data Apps with Streamlit and Copilot.
This is the second time I’ve run this workshop, and I’ve made several improvements based on what I learned the first time.
If you work in Python and want to turn your analyses into interactive, shareable tools, this workshop is designed for you. We’ll start from a Jupyter notebook and build a complete Streamlit app that lets users explore a dataset through interactive controls, charts, and maps. Along the way, we’ll use Copilot to speed up development and discover Streamlit features more efficiently.
What we’ll cover
- Structuring a Streamlit app
- Working with user input (select boxes, filters, etc.)
- Creating interactive graphics with Plotly
- Organizing the UI with columns and tabs
- Deploying your app to Streamlit Cloud
The workshop is hands‑on: you’ll build the app step‑by‑step, and by the end you’ll have a working project you can adapt to your own data.
What You’ll Build
Here’s a screenshot from the app we’ll build together:
The app lets users choose a state and demographic statistic, explore how it changes over time, and view the data as a chart, map, or table.
And while the example uses demographic data, the skills you’ll learn—structuring an app, building interactive controls, and creating dynamic visualizations—apply to any Streamlit project you want to build.
Who is this for?
- Data scientists and analysts who want to make their work more interactive
- Python users who want to build dashboards without learning web development
- Anyone curious about Streamlit or Copilot
How to Register
The workshop is hosted on O’Reilly, which is a membership platform. If you’re not already a member, I have a 30-day free trial you can use. To register for the workshop with the free trial:
- Start your free trial at this link
- Then register for the workshop itself
Also worth knowing: the workshop is recorded. So if July 9 doesn’t work for you, it’s still worth registering — you’ll have access to the recording.
I’d love to see you there.
Mariatta
Waitlisted for the Core Devs Sprint: When the Bad News was Also the Good News
Last week, I learned that I was one of 17 people waitlisted for the Python Core Devs Sprint at OpenAI this year.
A waitlist that long realistically means I probably won’t get in. I was sad, of course. The sprint alternates between Europe and the US. Traveling to Europe is … hard and complicated. I couldn’t go to last year’s in Europe, because of the location and work conflict. I was really hoping to go to this year’s US sprint. Next year it will be back in Europe, out of reach again. That’s potentially not sprinting for three years in a row.
Python Bytes
#484 All our tools
<strong>Topics covered in this episode:</strong><br> <ul> <li><strong><a href="https://pi.dev/?featured_on=pythonbytes">pi</a> + <a href="https://github.com/obra/superpowers/tree/main?featured_on=pythonbytes">superpowers</a></strong></li> <li><strong>Terminal: <a href="http://Warp.dev?featured_on=pythonbytes">Warp.dev</a> + <a href="https://ohmyz.sh/?featured_on=pythonbytes">OhMyZSH</a></strong></li> <li><strong>{<a href="https://blink.sh/?featured_on=pythonbytes">Blink</a>,<a href="https://sw.kovidgoyal.net/kitty/?featured_on=pythonbytes">kitty</a>} + <a href="https://mosh.org/?featured_on=pythonbytes">mosh</a> + <a href="https://github.com/tmux/tmux?featured_on=pythonbytes">tmux</a></strong></li> <li><strong><a href="https://www.anthropic.com/product/claude-code?featured_on=pythonbytes">Claude code</a></strong></li> <li><strong><a href="https://goodsnooze.gumroad.com/l/macwhisper?featured_on=pythonbytes">MacWhisper</a> or <a href="https://handy.computer?featured_on=pythonbytes">Handy</a></strong></li> <li><strong><a href="https://tailscale.com/?featured_on=pythonbytes">Tailscale</a></strong></li> <li><strong>Extras</strong></li> <li><strong>Joke</strong></li> </ul><a href='https://www.youtube.com/watch?v=wgKF3yvpxPU' style='font-weight: bold;'data-umami-event="Livestream-Past" data-umami-event-episode="484">Watch on YouTube</a><br> <p><strong>About the show</strong></p> <p>Sponsored by us! Support our work through:</p> <ul> <li>Our <a href="https://training.talkpython.fm/?featured_on=pythonbytes"><strong>courses at Talk Python Training</strong></a></li> <li>Six Feet Up is hosting a LinkedIn Live <strong>Connect with the hosts</strong></li> <li>Michael: <a href="https://fosstodon.org/@mkennedy">@mkennedy@fosstodon.org</a> / <a href="https://bsky.app/profile/mkennedy.codes?featured_on=pythonbytes">@mkennedy.codes</a> (bsky)</li> <li>Calvin: <a href="https://sixfeetup.social/@calvin?featured_on=pythonbytes">@calvinhp@sixfeetup.social</a> / <a href="https://bsky.app/profile/calvinhp.com?featured_on=pythonbytes">@calvinhp.com</a> (bsky)</li> <li>Show: <a href="https://fosstodon.org/@pythonbytes">@pythonbytes@fosstodon.org</a> / <a href="https://bsky.app/profile/pythonbytes.fm">@pythonbytes.fm</a> (bsky) Join us on YouTube at <a href="https://pythonbytes.fm/stream/live"><strong>pythonbytes.fm/live</strong></a> to be part of the audience. Usually <strong>Tuesday</strong> at 7am PT. Older video versions available there too. Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to <a href="https://pythonbytes.fm/friends-of-the-show">our friends of the show list</a>, we'll never share it.</li> </ul> <p><strong>Calvin #1: <a href="https://pi.dev/?featured_on=pythonbytes">pi</a> + <a href="https://github.com/obra/superpowers/tree/main?featured_on=pythonbytes">superpowers</a></strong></p> <ul> <li>terminal-first, open-source coding agent</li> <li>Session management is a first-class citizen</li> <li>Extension model is what makes pi special — it's aggressively composable</li> <li>Superpowers brings a structured software development methodology as loadable skills</li> <li>Steps back and asks you what you're really trying to do</li> <li>“hand you the keys to the car” mode vs guardrails might not be for everyone</li> </ul> <p><strong>Michael #2: Terminal: <a href="http://Warp.dev?featured_on=pythonbytes">Warp.dev</a> + <a href="https://ohmyz.sh/?featured_on=pythonbytes">OhMyZSH</a></strong></p> <ul> <li>If you’re using the base terminal with default settings, you have so much head-room for improvement.</li> <li>I’ve been using <a href="http://Warp.dev?featured_on=pythonbytes">Warp.dev</a> since Elvis talked me into it. ;)</li> <li>Remarkable terminal but the AI side of things is a bit junky, can be turned off</li> <li>OhMyZSH gives better autocomplete <ul> <li>e.g. git branch [HTML_REMOVED] lists all branches in the local repo!</li> </ul></li> <li><a href="http://Commandbookapp.com?featured_on=pythonbytes">Commandbookapp.com</a> is excellent to keep the terminal focused on terminal things and more server commands and other automation in Command Book.</li> </ul> <p><strong>Calvin #3: {<a href="https://blink.sh/?featured_on=pythonbytes">Blink</a>,<a href="https://sw.kovidgoyal.net/kitty/?featured_on=pythonbytes">kitty</a>} + <a href="https://mosh.org/?featured_on=pythonbytes">mosh</a> + <a href="https://github.com/tmux/tmux?featured_on=pythonbytes">tmux</a></strong></p> <ul> <li><a href="https://sw.kovidgoyal.net/kitty/?featured_on=pythonbytes"><strong>Kitty Terminal</strong></a> — GPU-accelerated terminal emulator for macOS, Linux, and Windows with support for graphics, ligatures, and a powerful tiling layout system built right in.</li> <li><a href="https://blink.sh/?featured_on=pythonbytes"><strong>Blink Shell</strong></a> — The go-to terminal for iPad/iPhone power users; full SSH and Mosh client with a gorgeous interface built specifically for mobile professional workflows.</li> <li><a href="https://mosh.org/?featured_on=pythonbytes"><strong>Mosh</strong></a> — Mobile Shell replaces SSH for remote connections, surviving network switches, sleep cycles, and flaky Wi-Fi with zero dropped sessions — essential for staying connected to long-running agentic jobs.</li> <li><a href="https://github.com/tmux/tmux?featured_on=pythonbytes"><strong>tmux</strong></a> — Terminal multiplexer that keeps sessions alive on your Linux server indefinitely; detach from a Mosh session on your Mac, reconnect from your iPad, and your agent is right where you left it.</li> <li><strong>The combo</strong> — Kitty or Blink + Mosh + tmux creates a "persistent remote brain" pattern: your beefy Linux homelab runs the compute-heavy agent sessions 24/7, and any device becomes a thin client to drop in and out at will.</li> </ul> <p><strong>Michael #4: <a href="https://www.anthropic.com/product/claude-code?featured_on=pythonbytes">Claude code</a></strong></p> <ul> <li>I prefer the IDE experience, the new PyCharm + Claude integration is really good. VS Code too. Why IDE? Because we should still be present with our code and managing context is much easier.</li> <li>Use the best/latest models on high thinking. “Speed” is not your friend, it’s just shortcuts.</li> <li>Create skills and agents and use them.</li> <li>Curate your own rules (e.g. Talk Python’s <a href="http://Claude.md?featured_on=pythonbytes">Claude.md</a>)</li> <li>Works well on non-coding things. Just create a folder, put a ton of files in there and it’s like NotebookLM + Chat + more.</li> </ul> <p><strong>Calvin #5: <a href="https://goodsnooze.gumroad.com/l/macwhisper?featured_on=pythonbytes">MacWhisper</a> or <a href="https://handy.computer?featured_on=pythonbytes">Handy</a></strong></p> <ul> <li>Transcribes your speech using your choice of Whisper or Parakeet models.</li> <li>All transcription is done on your device, <strong>no data leaves your machine.</strong></li> <li>Automatic Speaker Recognition with local models.</li> <li>Handy is more basic, but open source and runs on all platforms.</li> </ul> <p><strong>Michael #6: <a href="https://tailscale.com/?featured_on=pythonbytes">Tailscale</a></strong></p> <ul> <li>No need to open ports at all, Tailscale makes machines inside the same network accessible to each other</li> <li>Works great for laptops, desktops, etc. But also available for servers. <ul> <li>Though I still use cloud firewalls for servers.</li> </ul></li> <li><strong>How I use it</strong>: <ul> <li><strong>My dev database server</strong>, preloaded with QA data, is always running on my home mac mini m4 pro. All my apps look for that server before looking locally and tailscale makes them always accessible to each other</li> <li>My <strong>local LLMs expose OpenAI API compatible APIs</strong>. Tailscale makes these accessible even while traveling or at a coffee shop.</li> <li>Use my <strong>mini as an exit node</strong>. All traffic is routed outbound from my local fiber network. Great to restricted IPs like accessing my servers without caring about the local IP.</li> <li>Screen share back to my home machines even while traveling.</li> </ul></li> <li>Listen to the <a href="https://talkpython.fm/episodes/show/546/self-hosting-apps-for-python-people?featured_on=pythonbytes">Talk Python episode with Alex</a> for a deeper conversation.</li> </ul> <p><strong>Extras</strong></p> <p>Calvin:</p> <ul> <li><a href="https://www.telescopo.app?featured_on=pythonbytes">Telescopo</a> great Mac Markdown viewer/editor. Michael:</li> <li>One more: <a href="https://typora.io/?featured_on=pythonbytes">Typora markdown</a> editor.</li> <li>Created <a href="https://mkennedy.codes/docs/?featured_on=pythonbytes">formal documentation for many of my open source packages</a> using <a href="https://posit-dev.github.io/great-docs/?featured_on=pythonbytes">Great Docs</a>.</li> <li>Via Mark Little: <a href="https://www.anthropic.com/news/fable-mythos-access?featured_on=pythonbytes">Statement on the US government directive to suspend access to Fable 5 and Mythos 5</a></li> </ul> <p><strong>Joke: <a href="https://x.com/pr0grammerhum0r/status/2063078450311598430?s=12&featured_on=pythonbytes">No second date</a></strong></p>
HoloViz
HoloViz for LLMs
June 15, 2026
Kay Hayen
Nuitka Release 4.1
This is to inform you about the new stable release of Nuitka. It is the extremely compatible Python compiler, “download now”.
This release adds many new features and corrections with a focus on async code compatibility, missing generics features, and Python 3.14 compatibility and Python compilation scalability yet again.
Bug Fixes
Python 3.14: Fix, decorators were breaking when disabling deferred annotations. (Fixed in 4.0.1 already.)
Fix, nested loops could have wrong traces lead to mis-optimization. (Fixed in 4.0.1 already.)
Plugins: Fix, run-time check of package configuration was incorrect. (Fixed in 4.0.1 already.)
Compatibility: Fix,
__builtins__lacked necessary compatibility in compiled functions. (Fixed in 4.0.1 already.)Distutils: Fix, incorrect UTF-8 decoding was used for TOML input file parsing. (Fixed in 4.0.1 already.)
Fix, multiple hard value assignments could cause compile time crashes. (Fixed in 4.0.1 already.)
Fix, string concatenation was not properly annotating exception exits. (Fixed in 4.0.2 already.)
Windows: Fix,
--verbose-outputand--show-modules-outputdid not work with forward slashes. (Fixed in 4.0.2 already.)Python 3.14: Fix, there were various compatibility issues including dictionary watchers and inline values. (Fixed in 4.0.2 already.)
Python 3.14: Fix, stack pointer initialization to
localspluswas incorrect to avoid garbage collection issues. (Fixed in 4.0.2 already.)Python 3.12+: Fix, generic type variable scoping in classes was incorrect. (Fixed in 4.0.2 already.)
Python 3.12+: Fix, there were various issues with function generics. (Fixed in 4.0.2 already.)
Python 3.8+: Fix, names in named expressions were not mangled. (Fixed in 4.0.2 already.)
Plugins: Fix, module checksums were not robust against quoting style of module-name entry in YAML configurations. (Fixed in 4.0.2 already.)
Plugins: Fix, doing imports in queried expressions caused corruption. (Fixed in 4.0.2 already.)
UI: Fix, support for
uv_buildin the--projectoption was broken. (Fixed in 4.0.2 already.)Compatibility: Fix, names assigned in assignment expressions were not mangled. (Fixed in 4.0.2 already.)
Python 3.12+: Fix, there were still various issues with function generics. (Fixed in 4.0.3 already.)
Clang: Fix, debug mode was disabled for clang generally, but only ClangCL and macOS Clang didn’t want it. (Fixed in 4.0.3 already.)
Zig: Fix,
--windows-console-mode=attach|disablewas not working when using Zig. (Fixed in 4.0.3 already.)macOS: Fix, yet another way self dependencies can look like, needed to have support added. (Fixed in 4.0.3 already.)
Python 3.12+: Fix, generic types in classes had bugs with multiple type variables. (Fixed in 4.0.3 already.)
Scons: Fix, repeated builds were not producing binary identical results. (Fixed in 4.0.3 already.)
Scons: Fix, compiling with newer Python versions did not fall back to Zig when the developer prompt MSVC was unusable, and error reporting could crash. (Fixed in 4.0.4 already.)
Zig: Fix, the workaround for Windows console mode
attachordisablewas incorrectly applied on non-Windows platforms. (Fixed in 4.0.4 already.)Standalone: Fix, linking with Python Build Standalone failed because
libHacl_Hash_SHA2was not filtered out unconditionally. (Fixed in 4.0.4 already.)Python 3.6+: Fix, exceptions like
CancelledErrorthrown into an async generator awaiting an inner awaitable could be swallowed, causing crashes. (Fixed in 4.0.4 already.)Fix, not all ordered set modules accepted generators for update. (Fixed in 4.0.5 already.)
Plugins: Disabled warning about rebuilding the
pytokensextension module. (Fixed in 4.0.5 already.)Standalone: Filtered
libHacl_Hash_SHA2from link libs unconditionally. (Fixed in 4.0.5 already.)Debugging: Disabled unusable unicode consistency checks for Python versions 3.4 to 3.6. (Fixed in 4.0.5 already.)
Python3.12+ Avoided cloning call nodes on class level which caused issues with generic functions in combination with decorators. (Added in 4.0.5 already.)
Python 3.12+: Added support for generic type variables in
async deffunctions. (Added in 4.0.5 already.)UI: Fix, flushing outputs for prompts was not working in all cases when progress bars were enabled. (Fixed in 4.0.6 already.)
UI: Fix, unused variable warnings were missing at C compile time when using
zigas a C compiler. (Fixed in 4.0.6 already.)Scons: Fix, forced stdout and stderr paths as a feature was broken. (Fixed in 4.0.6 already.)
Fix, replacing a branch did not accurately track shared active variables causing optimization crashes. (Fixed in 4.0.7 already.)
macOS: Fix, failed to remove extended attributes because files need to be made writable first. (Fixed in 4.0.7 already.)
Fix, dict
popandsetdefaultusing with:=rewrites lacked exception-exit annotations for un-hashable keys. (Fixed in 4.0.8 already.)Python 3.13: Fix, the
__parameters__attribute of generic classes was not working. (Fixed in 4.0.8 already.)Python 3.11+: Fix, starred arguments were not working as type variables. (Fixed in 4.0.8 already.)
Python2: Fix,
FileNotFoundErrorcompatibility fallback handling was not working properly. (Fixed in 4.0.8 already.)Compatibility: Fix, loop ownership check in value traces was missing, causing issues with nested loops.
Windows: Improved
--windows-console-mode=attachto properly handle console handles, enabling cases likeos.systemto work nicely.Python2: Fix, there was a compatibility issue where providing default values to the
mkdtempfunction was failing.Windows: Fix, there were spurious issues with C23 embedding in 32-bit MinGW64 by switching to
coff_objresource mode for it as well.Plugins: Fix, the
post-import-codeexecution could fail because the triggering sub-package was not yet available insys.modules.UI: Fix, listing package DLLs with
--list-package-dllswas broken due to recent plugin lifecycle changes.UI: Fix,
--list-package-exewas not working properly on non-Windows platforms failing to detect executable files correctly.UI: Handled paths starting with
{PROGRAM_DIR}the same as a relative path when parsing the--onefile-tempdir-specoption.Plugins: Followed multiprocessing
forkserverchanges for newer Python versions.Python 3.12+: Fix, generic class type parameters handling was incorrect.
Python 3.12: Fix, deferred evaluation of type aliases was failing.
Python 3.12+: Aligned
sumbuilt-in float summation with CPython’s compensated sum for better accuracy.Python 3.10+: Fix, uncompiled coroutine
throw()return handling was incorrect, restoring completed coroutine results viaStopIteration.valuerather than exposing them as ordinary return values to the outer await chain.Python 3.13+: Fix, uncompiled coroutine
cancel()/awaitsuspension handling was incorrect, improved to ensure integration compatibility.macOS: Made finding
create-dmgmore robustly by also checking the Homebrew path for Intel and fromPATHproperly.Compatibility: Fix, class frames were not exposing frame locals.
UI: Detected
static-libpythonproblems, which affected some forms of Anaconda.Distutils: Rejected
--projectmixed with--mainarguments as it is not useful.macOS: Fix,
zigfromPATHor fromziglangwas not being used.Distutils: Fix, the wrong
module-rootconfig value was being checked foruvbuild backend.macOS: Fix, was attempting to change removed (rejected) DLLs, which of course failed and errored out.
Python 3.14: Fix, tuple reuse was not fully compatible, potentially causing crashes due to outdated hash caches.
Fix, fake modules were still being attempted to located when imported by other code, which could conflict with existing modules.
Python 3.5+: Fix, failed to send uncompiled coroutines the sent in value in
yield from.Fix, older
gcccompilers lacking newer intrinsic methods had compilation issues that needed to be addressed.Standalone: Fix, multiphase module extension modules with post-load code were not working properly.
Fix, Avoid using the non-inline copy of
pkg_resourceswith the inline copy of Jinja2. These could mismatch and cause errors.Fix, loops could make releasing of previous values very unclear, causing optimization errors.
Fix,
incbinresource mode was not working with oldgccC++ fallback.Python 3.4 to 3.6: Fix, bytecode demotion was not working properly for these versions, also bytecode only files not working.
Plugins: Added a check for the broken
patchelfversions 0.10 and 0.11 to prevent breaking Qt plugins.Android: Allowed
patchelfversion 0.18 on Android.Windows: Fix, the header path for self uninstalled Python was not detected correctly.
Release: Fix, inclusion of the
pkg_resourcesinline copy for Python 2 to source distributions was missing.UI: Detected the OBS versions of SUSE Linux better.
Suse: Allowed using
patchelf0.18.0 there too.Python 3.11: Fix, package and module dicts were not aligned close enough to avoid a CPython bug.
Fix, unbound compiled methods could crash when called without an object passed.
Standalone: Fix, multiphase module extension modules with postload. (Fixed in 4.0.8 already.)
Onefile: Fix, while waiting for the child, it may already be terminated.
macOS: Removed existing absolute rpaths for Homebrew and MacPorts.
Python 3.14: Avoided warning in CPython headers.
Python 3.14: Followed allocator changes more closely.
Compatibility: Avoided using
pkg_resourcesfor Jinja2 template location for loading.No-GIL: Applied some bug fixes to get basic things to work.
Package Support
Standalone: Add support for newer
paddleversion. (Added in 4.0.1 already.)Standalone: Add workaround for refcount checks of
pandas. (Fixed in 4.0.1 already.)Standalone: Add support for newer
h5pyversion. (Added in 4.0.2 already.)Standalone: Add support for newer
scipypackage. (Added in 4.0.2 already.)Plugins: Revert accidental
os.getenvoveros.environ.getchanges in anti-bloat configurations that stopped them from working. Affected packages arenetworkx,persistent, andtensorflow. (Fixed in 4.0.5 already.)Standalone: Added missing DLLs for
openvino. (Added in 4.0.7 already.)Enhanced the package configuration YAML schema by adding the
relative_toparameter forfrom_filenamesDLL specification, avoiding error-prone purely relative paths.Standalone: Fix,
flet_desktopapp assets were missing, now preserving the packaged runtime and sidecar DLLs.Standalone: Added support for the
tyropackage.Standalone: Added data files for the
perfettopackage.Standalone: Added support for
anyioprocess forking.Standalone: Added support for the
plotly.graphpackage.Anaconda: Fix, dependencies for the
numpyconda package on Windows were incorrect.Plugins: Enhanced the auto-icon hack in PySide6 to use compatible class names.
Standalone: Fix, Qt libraries were duplicated with
PySide6WebEngine framework support on macOS.Plugins: Fix, automatic detection of
mypycruntime dependencies was including all top level modules of the containing package by accident. (Fixed in 4.0.5 already.)Anaconda: Fix,
delvewheelplugin was not working with Python 3.8+. This enhances compatibility with installed PyPI packages that use it for their DLLs. (Fixed in 4.0.6 already.)Plugins: Fix, our protection workaround could confuse methods used with
PySide6.
New Features
UI: Added the
--recommended-python-versionoption to display recommended Python versions for supported, working, or commercial usage.UI: Add message to inform users about
Nuitka[onefile]if compression is not installed. (Added in 4.0.1 already.)UI: Add support for
uv_buildin the--projectoption. (Added in 4.0.1 already.)Onefile: Allow extra includes as well. (Added in 4.0.2 already.)
UI: Add
nuitka-project-setfeature to define project variables, checking for collisions with reserved runtime variables. (Added in 4.0.2 already.)Scons: Added new option to select
--reproduciblebuilds or not. (Added in 4.0.6 already.)Python 3.10+: Added support for
importlib.metadata.package_distributions(). (Added in 4.0.8 already.)Plugins: Added support for the multiprocessing
forkservercontext. (Added in 4.0.8 already, for 4.1 Python 3.6 and earlier, as well as 3.14 support were added too.)Reports: Added structured resource usage (
rusage) performance information to compilation reports.Reports: Included individual module-level C compiler caching (
ccache/clcache) statistics in compilation reports.Added support for detecting and correctly resolving the Python prefix for the
PyEnv on HomebrewPython flavor.macOS: Added support for
rusageinformation for Scons.UI: Added the
__compiled__.extension_filenameattribute to give the real filename of the containing extension module.Windows: Added support for
--clangor ARM. (Added in 4.0.8 already.)Windows: Added support for resources names as not just integers, important when we copy them from template files.
MacPorts: Added basic support for this Python flavor. More work will be needed to get it to work fully though.
Optimization
Avoid including
importlib._bootstrapandimportlib._bootstrap_external. (Added in 4.0.1 already.)Linux: Cached the
syscallused for time keeping during compilation to avoid loadinglibcfor each trace. (Added in 4.0.8 already.)UI: Output a warning for modules that remain unfinished after the third optimization pass.
Added an extra micro pass trigger when new variables are introduced or variable usage changes severely, ensuring optimizations are fully propagated, avoiding unnecessary extra full passes.
Provided scripts to compile Python statically with PGO tailored for Nuitka on Linux, Windows, and macOS.
Added support for running the Data Composer tool from a compiled Nuitka binary without spawning an uncompiled Python process.
Enhanced the usage of
vectorcallforPyCFunctionobjects by directly checking for its presence instead of relying purely on flags, allowing more frequent use of this faster execution path.Cached frequently used declarations for top-level variables to speed up C code generation.
Sped up trace collection merging by avoiding unnecessary set creation and using a set instead of a list for escaped traces.
Optimized plugin hook execution by tracking overloaded methods and added an option to show plugin usage statistics.
Improved performance of module location by avoiding unnecessary module name reconstruction and redundant filesystem checks for pre-loaded packages.
Improved the caching of distribution name lookups to effectively avoid repeated IO operations across all package types.
Plugins: Cached callback plugin dispatch for
onFunctionBodyParsingandonClassBodyParsingto skip argument computation when no plugin overrides them.Python 3.13: Handled sub-packages of
pathlibas hard modules.Handled hard attributes through merge traces as well.
Made constant blobs more compact by avoiding repeated identifiers and unnecessary fields.
Enhanced Python compilation scripts further. (Fixed in 4.0.8 already.)
Recognized late incomplete variables better. (Fixed in 4.0.8 already.)
Made constant blobs more compact. (Fixed in 4.0.8 already.)
Optimized calls with only constant keywords and variable posargs too.
Anti-Bloat
Fix, memory bloat occurred when C compiling
sqlalchemy. (Fixed in 4.0.2 already.)Avoid using
pydocinPySimpleGUI. (Added in 4.0.2 already.)Avoided using
doctestfromzodbpickle. (Added in 4.0.5 already.)Avoided inclusion of
cythonwhen usingpyav. (Added in 4.0.7 already.)Avoided including
typing_extensionswhen usingnumpy. (Added in 4.0.7 already.)
Organizational
UI: Relocated the warning about the available source code of extension modules to be evaluated at a more appropriate time.
Debian: Remove recommendation for
libfuse2package as it is no longer useful.Debian: Used
platformdirsinstead ofappdirs.Debugging: Removed Python 3.11+ restriction for
clang-formatas it is available everywhere, even Python 2.7, and we still want nicely formatted code when we read things. (Added in 4.0.6 already.)Removed no longer useful inline copy of
wax_off. We have our own stubs generator project.Release: Added missing package to the CI container for building Nuitka Debian packages.
Developer: Updated AI instructions for creating Minimal Reproducible Examples (MRE) to skip unneeded C compilation.
Debugging: Added an internal function for checking if a string is a valid Python identifier.
AI: Added a task in Visual Studio Code to export the currently selected Python interpreter path to a file, making it available as “python” and “pip” matching the selected interpreter. This makes it easier to use a specific version with no instructions needed.
AI: Updated the rules to instruct AI to only generate useful comments that add context not present in the code.
Containers: Added template rendering support for Jinja2 (
.j2) container files in our internal Podman tools.Projects: Clarified the current status and rationale of Python 2.6 support in the developer manual.
Debugging: Added experimental flag
--experimental=ignore-extra-micro-passto allow ignoring extra micro pass detection.Visual Code: Added integration scripts for
bashandzshautocompletion of Nuitka CLI options. These are now also integrated into Visual Studio Code terminal profiles and the Debian package.RPM: Included the Python compile script for Linux.
RPM: Removed the requirement for
distutilsin the spec.
Tests
Install only necessary build tools for test cases.
Avoided spurious failures in reference counting tests due to Python internal caching differences. (Fixed in 4.0.3 already.)
Fix, the parsing of the compilation report for reflected tests was incorrect.
Python 3.14: Ignored a syntax error message change.
Python 3.14: Added test execution support options to the main test runner to use this version as well.
Fix, the runner binary path was mishandled for the third pass of reflected compilations.
Removed the usage of obsolete plugins in reflected compilation tests.
Debugging: Prevented boolean testing of
namedtuplesto avoid unexpected bugs.Added the
Testsuffix to syntax test files and disabled “python” mode and spell checking for them to resolve issues reported in IDEs.Fix, newline handling in diff outputs from the output comparison tool was incorrect.
Covered
post-import-codefunctionality with a new subpackage test case.Prevented the program test suite from running an unnecessary variant to save execution time.
macOS: Ignored differences from GUI framework error traces in headless runs in output comparisons.
Reflected test for Nuitka, where it compiles itself and compares its operation has been restored to functional state.
Used the new method to clear internal caches if available for reference counts.
Disabled running nested loops test with Python 2.6.
Containers: Detected Python 2 defaulting containers in Podman tooling.
Cleanups
UI: Fix, there was a double space in the Windows Runtime DLLs inclusion message. (Fixed in 4.0.1 already.)
Onefile: Separated files and defines for extra includes for onefile boot and Python build.
Scons: Provided nicer errors in case of “unset” variables being used, so we can tell it.
Refactored the process execution results to correctly utilize our
namedtuplesvariant, that makes it easier to understand what code does with the results.Quality: Enabled automatic conversion of em-dashes and en-dashes in code comments to the autoformat tool. AI won’t stop producing them and they can cause
SyntaxErrorfor older Python versions, nor is unnecessarily using UTF-8 welcome.Ensured that cloned outline nodes are assigned their correct names immediately upon creation, that avoids inconsistencies during their creation.
Quality: Updated to the latest versions of
blackand adopted a fasterisortexecution by caching results.Quality: Modified the PyLint wrapper to exit gracefully instead of raising an error when no matching files require checking.
Quality: Avoided checking YAML package configuration files twice, since autoformat already handles them.
Quality: Ensured that YAML package configuration checks output the original filename instead of the temporary one when a failure occurs.
Quality: Prevented pushing of tags from triggering git pre-push quality checks.
Quality: Silenced the output of
optipngandjpegoptimduring image optimization auto-formatting.Visual Code: Added the generated Python alias path file to the ignore list.
Quality: Enabled auto-formatting for the Nuitka devcontainer configuration file.
Watch: Avoided absolute paths in compilation to make reports more comparable across machines.
Quality: Changed
mdformatchecks to run only once and silently.Scons: Disabled format security errors in debug mode and moved Python-related warning disables into common build setup code.
Quality: Updated to the latest
deepdiffversion.Scons: Avoided MSVC telemetry since it can produce outputs that break CI.
Debugging: Enhanced non-deployment handler for importing excluded modules.
Split import module finding functionality into more pieces for enhanced readability.
Debugging: Added more assertions for constants loading and checking.
macOS: Dropped the
universaltarget arch.Debugging: Added more traces for deep hash verification.
Summary
This release builds on the scalability improvements established in 4.0, with enhanced Python 3.14 support, expanded package compatibility, and significant optimization work.
The --project option seems usable now.
Python 3.14 support remains experimental, but only barely made the cut, and probably will get there in hotfixes. Some of the corrections came in so late before the release, that it was just not possible to feel good about declaring it fully supported just yet.
June 14, 2026
PyPy
A new benchmark runner for PyPy
The https://speed.pypy.org site has been running the PyPy benchmark suite since 2010. Our first benchmarking machine was called tannit, and it faithfully ran the suite from May 2010 to Dec 2016. For a brief period in the middle we had a machine called speed-python, but tannit was the gold standard. In June 2016 we started running benchmarks on our current machine, benchmarker (Intel i7-7700). It has been graciously sponsored by Baroque Software. Based on an Ubuntu xenial chroot, the machine has been quite stable but over the years has had a few kernel exploits blocked in firmware that changed its base performance.
It is time to update. Rather than use the same machine with updated software, we decided to opt for different hardware. Since the beginning of May we have been running the benchmark suite on benchmarker2: an AMD Ryzen 5 3600 machine. In order to try to stabilize benchmarks the machine was set up:
- without SMT (hyper-threading)
- using
cpusetto partition CPUs 3,4,5 off (the CPU has 2 CCD chiplets so the CPU sets are truly independent, the reason we chose the Zen2 architecture) and use them exclusively for benchmarking - disable turbo speed strategy.
It runs debian13 as a base operating system, and the benchmarks run in a
manylinux2_28 docker, which provides gcc14.
In order to establish a baseline, I compiled CPython 3.11.5 with:
./configure --prefix=/opt/cpython-3.11 --enable-optimizations \ --with-computed-gotos --enable-shared LDFLAGS='-Wl,-rpath,\$$ORIGIN/../lib'
The difference between the two machines is striking: where the xenial image (with GCC 5.4) benchmark comparison to CPython 3.11.9 shows a 3x improvement when run on PyPy on benchmarker, the newer machine with the newer compiler and a fresh baseline shows a 4.3x improvement. I can only speculate that the major differences between the results is:
- The CPython 3.11.9 run was done in June 2024. This was before some firmware kernel changes applied to the host machine that slowed it down. I did notice at the time the exploit migitagion firmware was applied that the overall comparison dropped from 3.3x to 3x, but felt the additional protection was warrented.
- The newer software image uses GCC 14, where the older one used GCC 5.
- The AMD machine has 32MB of L3 cache, the Intel machine has 8MB.
- The AMD machine uses RAM at 3200MHz, the Intel at 2400MHz.
The last 3 points may affect PyPy more than CPython, since PyPy's JIT is more memory intensive and the RPython codegen may be handled better by newer compilers.
This is the first step in an overhaul of PyPy's infrastructure. Other plans in the pipeline:
- Move all the buildbot builds from
manylinux_2014tomanylinux2_28-based images. This will match the move on benchmarker2. It will require some adaptations so that tests will pass on the newer compiler, see pypy/pypy#5488. This will mean an ABI break, so the next PyPy release will leave behind the 7.3.x series. - Think about updating our use of buildbot 0.8.8, which is woefully out of date. Since we have a heavily customized summary page, and the twistd-based endpoints are not supported on buildbot 0.9 and up, we set up a build-summary alternative that is synchronized to the buildbot work.
- Perhaps make more use of the free GitHub actions workers to replace or enhance the buildbot workers. Some of that can be seen in PR 5488. The build-summary service is also able to ingest github action testing results.
- Continue to push on in CPython compatibility, performance improvements, and bugfixes, as well as work on a PyPy 3.12 version
Help of course is welcome.
Matti
Eli Bendersky
Plugins case study: Pluggy
Recently I came upon Pluggy, a Python library for developing plugin systems. It was originally developed as part of the pytest project - known for its rich plugin ecosystem - and later extracted into a standalone library. You're supposed to reach out for Pluggy if you want to add a plugin system to your tool or library and want to use something proven rather than rolling your own.
In this post I will share some notes on how Pluggy works, and will then review how it aligns with the fundamental concepts of plugin infrastructures.
Using Pluggy
Pluggy is built around the concept of hooks: functions that host applications or tools (from here on, just "hosts") expose and plugins implement. A host exposes hooks by using a decorator returned from pluggy.HookspecMarker and a plugin implements this hook using a decorator returned from pluggy.HookimplMarker.
Pluggy's documentation explains this fairly well; in this post, I'll show how to implement the htmlize tool with some plugins, introduced in the original article in my plugin series.
As a reminder, htmlize is a toy tool that takes markup notation similar to reStructuredText, and converts it to to HTML. It supports plugins to handle custom "roles" like:
some text :role:`customized text` and more text
As well as plugins that do arbitrary processing on the entire text.
Defining hooks
Out host defines two hooks:
import pluggy
hookspec = pluggy.HookspecMarker("htmlize")
@hookspec(firstresult=True)
def htmlize_role_handler(role_name):
"""Return a function accepting role contents.
The function will be called with a single argument - the role contents, and
should return what the role gets replaced with.
"""
pass
@hookspec
def htmlize_contents(post, db):
"""Return a function accepting full document contents.
The function will be called with a single argument - the document contents
(after paragraph splitting and role processing), and should return the
transformed contents.
"""
pass
A hook is created by calling HookspecMarker with the project's name. This project name has to match between the host and its plugins. Pluggy is permissive about what hooks accept as parameters and what they return; for maximal flexibility and to stay true to the original htmlize example, our hooks return functions.
To accompany this HookspecMarker, the host also defines a HookimplMarker with the same name:
hookimpl = pluggy.HookimplMarker("htmlize")
This is used by plugins to attach to hooks when they're loaded.
Loading plugins in the host
The host's main function loads plugins at startup as follows:
pm = pluggy.PluginManager("htmlize")
pm.add_hookspecs(hookspecs)
pm.load_setuptools_entrypoints("htmlize")
hookspecs is our Python module containing the hooks shown above. load_setuptools_entrypoints is Pluggy's helper for loading plugins that were pip-installed into the same environment and registered as setuptools entry points. It's a way to signal - in one's setup.py or pyproject.toml file - some metadata that projects can review at runtime. In our project, the plugins register themselves with this section in the pyproject.toml file:
[project.entry-points.htmlize]
tt = "tt"
This says "for entry point htmlize, define a new entry named tt". Pluggy's load_setuptools_entrypoints then uses importlib.metadata to access this information.
Note that Pluggy doesn't require using this mechanism. Hosts can implement any plugin discovery method they want, and add plugins directly to their PluginManager with the register method. But this is the mechanism used for pytest and many other projects; it makes it very easy to automatically discover and register plugins that are installed with pip and equivalent tools.
Invoking plugins
Once PluginManager loads the plugins, invoking them is straightforward; here's how htmlize invokes the contents hooks [1]:
# Build full contents back again, and ask plugins to act on
# contents.
contents = ''.join(parts)
for handler in plugin_manager.hook.htmlize_contents(post=post, db=db):
contents = handler(contents)
return contents
Generally, hook invocations return a list of all the hooks attached to by different plugins (a single host application can have multiple plugins installed and attaching to the same hook). When the host invokes the hook as shown above, the default order is LIFO, but plugins can affect this with hook options like tryfirst and trylast.
Implementing hooks in plugins
Here's our entire narcissist plugin that's attaching to the contents hook:
import htmlize
@htmlize.hookimpl
def htmlize_contents(post, db):
repl = f'<b>I ({post.author})</b>'
def hook(contents):
return re.sub(r'\bI\b', repl, contents)
return hook
Some notes:
- It expects htmlize to be installed; as discussed previously, we rely on Pluggy's default install-based approach where both the host and plugins are installed into the same Python environment and can thus find each other. However, Pluggy supports any custom discovery method.
- It uses the hookimpl exported value shown earlier.
- It returns a function that acts on contents; this is the htmlize-specific contract (ABI, if you will) we've discussed before.
Fundamental plugin concepts in this case study
Let's see how this case study of Pluggy measures against the Fundamental plugin concepts that were covered several times on this blog.
It's important to remember that Pluggy is not a specific host application with a bespoke plugin system; rather, it's a reusable library for creating such plugin systems. Therefore, this is more of a meta case study.
Discovery
Generally, Pluggy leaves discovery logic to the user's discretion. Its PluginManager has a register method for adding plugins, and these can be discovered in any way the application chooses.
That said, Pluggy comes with one discovery mechanism built in - through the entry points process of Python packaging, as shown above. This is hugely convenient for a large number of applications, as long as both the application and its plugins are installed via standard Python packaging tools (which is a very reasonable assumption in the Python ecosystem).
Registration
In the entry point process, plugins register themselves by adding a [project.entry-points.<HOST-ID>] section in their pyproject.toml file.
Otherwise - as in the previous section - users are free to devise their own registration schemes.
Hooks
This one is easy, since it's called hooks in Pluggy parlance as well! Pluggy's implementation of hooks is rather elegant, with function decorators available for plugins to set. We've seen an example of this above with @htmlize.hookimpl decorating htmlize_contents.
Exposing an application API to plugins
Since Pluggy is designed for Python hosts and Python plugins, this one is fairly straightforward. The plugins typically assume the host project is already installed in the Python environment and its modules can be imported.
In our example, hookimpl is imported from htmlize by the plugin to accomplish this. It also shows how host data is passed to the plugin - the post and db parameters. These are APIs exposed by the host for the plugins' use.
Conclusion - is Pluggy worth it?
In footnote 2 of my original fundamental concepts of plugin infrastructures post, I wrote [2]:
This is probably why there are very few well-established plugin frameworks in existence (even in low-level languages like C or C++). It's too easy (and tempting) to roll your own.
I still believe my statement is true - plugin frameworks are very easy to create, and the functionality they provide is relatively small compared to their large surface area. In other words, this is a shallow API.
That said, Pluggy does provide some nice functionality for the more advanced uses of plugins:
- Automatic entry point registration mechanism - if you need it
- Signature validation
- Consistent plugin result collection across multiple hook attachments in a single plugin and across many plugins
- Plugin ordering with firstresult, tryfirst, trylast, etc.
- Hook "wrappers" for some special use cases
Are these worthwhile for your project? It really depends on the project, and it's always worth keeping the tradeoff between dependencies and project effort in mind.
Code
The full code repository for this post is available here.
| [1] | Here plugin_manager is the value previously returned from pluggy.PluginManager; in the previous code snippet it's saved into pm - the different variable name is because a function call is made and plugin_manager is the parameter name. |
| [2] | To be fair, that post predates the creation of Pluggy! |
Bob Belderbos
Why Rust does not need OOP
When I heard structs replace classes in Rust, I was a bit surprised. I thought, how can you do without classes? But as I started to learn Rust, I realized that structs, traits, ownership and composition help resist the temptation of OOP. In fact, Rust's approach to programming is more focused on data and behavior rather than objects.
Let's look at 5 reasons why Rust does not need OOP.
1. Composition
One major drawback of OOP is deep inheritance trees.
In classic OOP you would define class A, then class B inherits from A, then class C inherits from B, and so on. This can lead to a complex and fragile codebase where changes in one class can affect many others.
class Animal {}
class Dog extends Animal {}
class ServiceDog extends Dog {}
In What Rust Structs Taught Me About State Ownership I showed this example:
struct Tokenizer {
chars: Vec<char>,
position: usize,
}
impl Tokenizer {
fn advance(&mut self) -> Option<char> {
let ch = self.chars.get(self.position).copied();
self.position += 1;
ch
}
fn peek(&self) -> Option<char> {
self.chars.get(self.position).copied() // char is Copy, returns a value not a reference
}
}
We see a clear separation of data (the fields) and behavior (the methods). The Tokenizer struct holds the state, while the methods define how to interact with that state. This is a more flexible and modular approach than OOP's class-based design.
Rust also uses composition instead of inheritance. You can create complex types by combining simpler ones without the need for a class hierarchy.
struct Animal {}
struct Dog {
animal: Animal,
}
struct ServiceDog {
dog: Dog,
}
A great resource on this principle is Composition Over Inheritance, part of Brandon Rhodes' Python Patterns Guide.
For an example where I think OOP & inheritance went off the rails is Django's class-based views. The inheritance tree of those views is too deep making it an unpleasant API to work with, and the code so much harder to reason about. A better way is the more functional approach, see Luke Plant's Django Views — The Right Way.
2. Traits
In Python, think Protocols. In Java, think interfaces. In Rust, traits are a powerful way to define shared behavior without the need for a class hierarchy; polymorphism without inheritance.
Classic OOP:
Animal a = new Dog();
a.speak();
In Rust, you can achieve similar behavior using traits:
trait Speak {
fn speak(&self);
}
fn make_noise(x: &impl Speak) {
x.speak();
}
The advantage here is that you can implement the Speak trait for any type, and you don't need to have a common base class. This allows for more flexibility and code reuse.
Python has something similar with Protocols, which are part of the typing module. They allow you to define a set of methods that a class must implement, without requiring inheritance.
from typing import Protocol
class Speak(Protocol):
def speak(self) -> None: ...
def make_noise(x: Speak) -> None:
x.speak()
This is a more flexible alternative to ABCs (Abstract Base Classes) and allows for duck typing while still providing type safety. I wrote an article about this on Pybites.
Where OOP couples data and behavior, Rust's traits allow you to define behavior separately from data. This promotes code reuse and flexibility without the need for a rigid class structure.
Rust encourages:
struct User {}
trait Serialize {}
trait Validate {}
trait Persist {}
This is closer to the Single Responsibility Principle, the Unix philosophy of "do one thing and do it well", functional programming of data-oriented design with pure functions that operate on data, and composition over inheritance.
Hence Rust allows you to mix and match traits to create complex behavior without the need for a class hierarchy.
3. Ownership and borrowing
Many OOP patterns exist to control mutation and provide proper encapsulation. In Rust, ownership and borrowing rules ensure that data is accessed safely and efficiently.
fn process(data: Data) // takes ownership (moved in)
fn process(data: &Data) // borrows, read-only
fn process(data: &mut Data) // borrows, can mutate
Just by looking at the function signature in Rust, you can understand how data is being used and modified: who owns it, who mutates it, and when it goes out of scope. It eliminates the need for patterns like getters/setters, which are often used in OOP to control access to data. And these rules are enforced at compile time, not runtime.
4. Modularity
I came to the conclusion some time ago that Python's module scope is a great feature. It allows you to organize code in a way that is more flexible than OOP's class-based organization. In Rust, modules and crates provide a way to organize code without the need for classes.
Classic OOP:
public class Counter {
private int value;
public void increment() {
value += 1;
}
}
In Rust, you can use module-level functions and structs to achieve the same result:
mod internal {
pub struct Counter {
value: i32,
}
impl Counter {
pub fn increment(&mut self) {
self.value += 1;
}
}
}
Outside:
counter.value // inaccessible
counter.increment() // ok
Yes, increment is a mutating method, the same as a setter. The win isn't avoiding methods, it's two things.
First, the privacy boundary is the module, not the object: value is hidden from the whole module, and you can hide free functions and structs too, not just wrap fields in a class.
Second, you only write the method when you need to guard an invariant. If a field is just plain data, mark it pub and read it directly, no getter ceremony. Java's idiom nudges you to wrap every field in get/set whether it needs it or not.
So encapsulation lives at the module level, not the class level. It also leans toward a more functional style where pure functions operate on data without mutable state.
In Python you can also hide functions and variables at the module level:
def _private_function():
pass
But this does not prevent somebody importing it so you need fencing mechanisms like __all__ to control what gets imported. Python's _private is a suggestion, Rust's module privacy is enforced by the compiler.
5. Enums and pattern matching
In OOP, you often use class hierarchies to represent different types of objects. In Rust, you can use enums and pattern matching to achieve similar results without the need for a class hierarchy.
Classic OOP:
abstract class Shape {}
class Circle extends Shape {}
class Square extends Shape {}
In Rust, you can use enums to represent different shapes:
enum Shape {
Circle(f64),
Square(f64),
}
fn area(shape: Shape) -> f64 {
match shape {
Shape::Circle(r) => 3.14 * r * r,
Shape::Square(s) => s * s,
}
}
Not only is an enum more lightweight than a class hierarchy, it also pairs up really well with pattern matching handling different cases in a concise and (!) exhaustive manner. The compiler will not let you forget a case.
Conclusion
In short, OOP bundles data and behavior together which made a lot of sense to me for a long time. Learning Rust though, I am seeing new paradigms how the language designers have decoupled the two.
With Rust you get the good parts of OOP: encapsulation, abstraction and polymorphism, while dropping the less maintainable parts: inheritance trees, mutable state and coupling.
So to wrap up, here is a comparison of classic OOP -> Python -> Rust:
| Concern | Traditional OOP | Python | Rust |
|---|---|---|---|
| Encapsulation | Classes with private/public members | Modules + _private convention | mod + pub visibility |
| Polymorphism | Inheritance + virtual methods | Duck typing / Protocols | Traits |
| Reuse | Inheritance | Composition | Composition |
| State modeling | Class hierarchies | dict, dataclass, classes | struct + enum |
| Object lifecycle | GC / constructors | GC | Ownership + borrowing |
| Error handling | Exceptions | Exceptions | Result<T, E> + exhaustive matching |
Typical style evolution
Old-school OOP:
Object → Class → Inheritance → Framework
Modern Python:
Data → Functions → Composition → Protocols
Rust:
Data → Ownership → Traits → Composition
As you see Python gets you far and is versatile, but Rust's ownership and traits give you an even more reliable and maintainable way to structure your code without the need for OOP.
Different philosophy
I am not picking on Java or OOP, I've been a fan for a long time. Studying philosophy (e.g. Plato) gives you a deeper appreciation for this way of thinking. But it can also lead to overcomplication and unnecessary coupling.
It's good to learn the different paradigms and understand their strengths and weaknesses. In summary:
Traditional OOP:
"Model the world as interacting objects."
Python:
"We trust developers."
Which is awesome, but not without risk. It allows for great flexibility and rapid development, but it can also lead to bugs and maintenance issues if not used carefully.
Rust:
"Prove correctness to the compiler."
A newer paradigm for me, but the way Rust decouples data and behavior, enforces ownership and borrowing rules, and promotes composition over inheritance, all sit well with me.
Those things do lead to more reliable and maintainable code. It encourages you to think about your code in a way that is more focused on data and behavior rather than objects.
June 13, 2026
Armin Ronacher
Dangerous Technology For Americans Only
There is a bit of schadenfreude on Twitter right now about Anthropic being hit by the US government’s export control directive to suspend access to Fable and Mythos. Anthropic and their leadership have spent a lot of time and effort describing its own technology as dangerous and in need of strict controls and regulation. Now that the US government appears to have taken that framing seriously and told them to turn it off for foreign nationals I can see why people are making fun of that situation.
I understand the reaction, but I urge you to not entertain it for too long because it is a giant distraction. The important part is not that Anthropic’s safety language came back to bite them but the line the US government is drawing: this technology is apparently so powerful that only Americans should have it.
We are on a clear path towards a world of division. One should think that if a model is too dangerous for everyone, then it is too dangerous for Americans too. Instead the US is treating these models like weapons that need to be controlled. It is not just about capabilities, it is about racism and nationalism. If you have the wrong passport, you are not to be trusted. This is a very different thing from safety, and Europeans should pay close attention to it.
Safety and National Control
The directive, as Anthropic describes it, applies to foreign nationals whether they are inside or outside the United States, including foreign national Anthropic employees. That is an astonishing boundary if you think about it. We moved from “do not sell this model to hostile governments” to nationality itself being the defining boundary. This should be a wake-up call to Europeans in and outside the US, and quite frankly, any non US citizen.
A lot of AI safety discourse presents itself as universal: humanity, catastrophic risk, safeguards, responsible deployment. Even Anthropic’s own writings start out that way, but yet every time regulation is discussed there is an overtone of national security and that it cannot get into the wrong hands. It’s not just Anthropic, it’s the entire US based discourse on AI. The foundation is that the US has moral superiority and others are not to be trusted. That there are other countries are authoritarian, that they lack freedoms.
That should make us uncomfortable, not just Europeans, but particularly us. It is also a situation you cannot regulate yourself out of. European technology policy is entirely unprepared for this, because this is not a question of regulation but a question of might and power, something that Europe lacks.
Europe has spent years trying to regulate large American technology companies, sometimes for good reasons. I am not reflexively against that. The DMA matters because access matters. Users should have agency over their devices, their data, and the software they run. But regulation is a useless substitute for capability and we are lacking that. Regulation might try to force open doors but if those doors only come from American or Chinese companies, then that accomplishes very little.
Also let’s not be naive in that this is a negotiation of money and force. The US is in that position because the US has a mighty military. The US can bomb nations anywhere in the world, force international trade routes closed and get away with it. That’s true leverage.
Oh Europe
Europe is dependent on the United States in ways that are becoming increasingly impossible to ignore. We depend on American cloud providers, operating systems, developer platforms and now AI models and internet from satellites. We also depend on global semiconductor supply chains we do not control. If access to frontier AI becomes a matter of American national security policy, Europe is not a peer in that conversation and might not even be a market.
That is a humiliating position, but one that happened entirely intentionally.
European citizens and politicians still have not managed to move beyond blaming the EU for its failures. We built and maintained fragmented markets and then pretended we had a single one. We let company formation, hiring, equity compensation, tax, notaries, KYC, banking, and cross-border services remain much harder than they need to be and we are playing these rules against each other. Not just on the European level, but within every single member state. We protect the trusts and established enterprises, who are risk averse and entrenched, instead of trusting the next generation to build great companies. We created a culture where process becomes an excuse for low agency. We made it hard to build new and large companies and then act surprised when our most ambitious founders move somewhere else or just decided to incorporate their companies in the US.
Increasingly, Europeans who want to build very large technology companies move to the United States. They do it because the capital markets are better, the startup infrastructure is better, employee equity is better understood. I cannot blame anyone doing it, and I’m guilty of this myself as we have incorporated our holding in Delaware. If you are trying to raise serious money, hire aggressively, and move quickly, the US often looks like the only game in town. Because quite frankly: it is.
But this is why we are on a dangerous death spiral already. Talent leaves because the ecosystem is weak and the ecosystem stays weak because talent leaves. Infrastructure makes the world: build excellent swimming pools and you will grow a generation of great swimmers.
The temporary task is straightforward but uncomfortable: Europeans need to believe in themselves enough not to surrender to American gravity. Moving to the US as a founder or tech employee is rational and individually it is often the right decision. But if every ambitious person treats Europe as a lost cause, then Europe becomes one. If everyone with agency leaves, the only people left to shape the system are the people most comfortable with the system as it is. Then we really should not be surprised when nothing changes.
Europe needs more ambition, more ownership, more urgency, and more willingness to build. It needs less resignation. It needs to stop confusing regulation with strategy and dependency with virtue. We need to deregulate where rules serve mostly as protectionism. We need capital markets that can fund companies at the scale modern technology requires. We need employee ownership to become normal rather than exotic. We need a real single market for services, not just speeches about one. We need countries to stop fighting each other while claiming to act in the European interest.
Most importantly: we need to stop blaming the politicians. Too many European companies are adding to that bureaucracy entirely out of their own choice. They drown you in paperwork. At one point I had to sign a four page contract for a 120 Euro lamp at an Austrian retailer, just to pick up from their store 15 minutes later. Sometimes I cannot get a speaking engagement at a European event without someone sending me complex rights waivers over. It’s all just paperwork protection against potential downsides.
When we do not have the power to influence, we should at least understand why and where things are failing. Too many entrepreneurs are blaming EU regulation for failures that are originating within the member states. EU regulation is the result of a democratic process between countries that are lobbying in favor of their local industries against others in the same economic bloc. No amount of abolishment of the EU is going to fix this harsh reality. Nothing more demonstrates this as the inability for cross-border M&A in the European Union. It’s not the EU that blocks it, it’s the country that loses out.
Strengthening Europe is necessary because weakness makes us pawns. A Europe that cannot build, cannot finance, cannot coordinate and cannot defend its own interests will not be treated as an equal. It will be regulated around, export-controlled around, consulted after the fact or not consulted at all.
The American Trap
I do not want the lesson to be that Europe simply needs to turn itself into a copy of the United States. The US has solved some things that Europe has not. It has deep capital markets, a much stronger culture of ownership, a greater tolerance for risk, and institutions that often try to make progress possible rather than explain why it cannot happen. It also has achieved an internal level of integration that is unparalleled in Europe. Tremendous advantages!
But the American path is not obviously a healthy one in all aspects. It tends to take paths with a lot of conflict and wars, a lot of internal societal division and deep inequalities. It centralizes powers away from citizens in the presidency and people with money. You are still trading one set of failures for another. You are at the whim of the US government and its strict rules and regulations. The US barely manages to uphold the rights for its own citizens today.
We should be honest about both sides. You do not win by pretending that Europe is fine. You also do not win by pretending that America has figured everything out.
We must not be blind to all the signs of how international cooperation is falling apart around us. The US no longer talks to European governments before implementing orders that directly affect Europeans. It is threatening to take Greenland, the territory of Denmark, one of its oldest allies. Treaties, alliances and institutions have lost all their worth.
All that matters even if our own lives are focused on building companies, creating wealth, hiring people and making things. Our individual path to success is one thing, but it depends on a world where contracts work, visas work and don’t change on a moment’s notice, trade routes stay open, payment systems function, and families are not torn apart by border regimes or wars. If the world descends into chaos, our basic needs cannot be considered met just because we have a great salaries or equity or investors that trust us.
This is why strengthening Europe cannot be the final goal. A stronger EU is, at best, a temporary defense against a darker world and not an excuse to replace American nationalism with European nationalism. The long-term answer cannot be bigger and bigger blocs fighting over who may use which model, which chip, which cloud or which trade route.
The Way Out Is Cooperation
I’m not asking here for Europeans to get their shit together just to compete with the US or China. Maybe I hope that this is a thing that develops, but the goal absolutely cannot be that we accept the deterioration of international relationships long term.
I truly believe that Open Source matters and international cooperation matters. It is not a magical answer to every problem, but it is one of the few paths we have that does not naturally lead to total concentration of power.
If frontier AI becomes something only large corporations and governments can control, then everyone else becomes dependent on their judgment. That is a bad place to be. Corporations will optimize for their incentives, as well structured as they might be, and governments will optimize for more and more power. Right now we’re on a path in which access to general-purpose capability is mediated by a small number of actors with tremendous powers.
I’m not naive in pretending AI cannot carry inherent risks. Open systems are messy, they can be misused and they create uncomfortable questions about dual-use capabilities. I do not want to wave that away but closed systems do not make those questions disappear either. Moving the power to decide into fewer hands is not a solution I believe in. And I would have the same opinion if I was a US citizen living in the US.
Any path that puts large blocs in a constant fight against each other has despicable downstream effects that result in the removal of individual rights. It’s entirely pointless for the US to talk about freedoms that do not extend to non-US citizens and the same is true for Europe or any other country. We might accept these restrictions temporarily, but we absolutely cannot accept them long term for the inhumane effects that they can cause.
If we believe this technology can be used for good, then broad access matters and our goal should be to restore the international rule of law, and not to further weaken it. If we find ourselves in a war against our friends from other countries, cold or hot, we have failed as society.
The world we should be working back toward is one of international cooperation, globalization in the best sense of the word, and human dignity. The internet has made our lives irreversibly international: every day people fall in love across borders, marry across languages, move across continents, and work with friends they may never meet in countries they may never visit. Identifying too strongly with any one country in that world is a fool’s errand.
Over the last decade too many of the people I got to know through Open Source were directly dragged into a war. I want to believe there is a way for us to break this cycle. We should be repairing failed states, rebuilding trust between people, and finding ways to cooperate again instead of letting the richest countries arm themselves and fight over who gets to control the future and narrative. Of course I want Europe to become stronger so it can stop being a pawn, but if we mistake that temporary need for the destination, I will be deeply disappointed.
The way out is not American supremacy, Chinese supremacy or European supremacy. The way out is to climb back toward cooperation before the alternative becomes war.
Artificial Intelligence is quickly becoming another instrument of militarization and national rivalry, when it could be one of the most powerful tools for cooperation we have. We should be using it to help people across societies and languages understand one another, not fighting over who gets to control it.
June 12, 2026
Real Python
The Real Python Podcast – Episode #299: EuroPython 2026: Celebrating 25 Years
What's happening at EuroPython 2026? The conference celebrates its 25th anniversary this year in Kraków, Poland. This week on the show, organizers Mia Bajić and Daria Linhart Grudzien join me to discuss this year's conference.
[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]
EuroPython
June Newsletter: Talks Schedule Released
Hi all Pythonistas! 👋
We have just one month left until we all meet up in Kraków, and we’ve got a lot of new stuff to tell you: the schedule is available, new keynote announcements, our 25 years of EuroPython celebrations (win a free ticket!), the release of our Speaker’s Orientation Workshop video on YouTube (in case you missed it!), remote ticket availability, a reminder about ticket prices (going up on June 26th!), plus plenty more 💚
🎉 Talk Schedule Available
Let’s start with the big one: the programme team have been working tirelessly to get the talk schedule finalised, and you can now read it, in full, over on our website. The talks this year were selected from a record breaking number of submissions, and we are really excited about the number of topics covered from such a wide range of speakers.
👉 Start noting down your ‘must see’ favourites now, and plan out your &aposjourney&apos through the conference: https://ep2026.europython.eu/schedule/
🎤 Keynote Announcements
Guido van Rossum, Łukasz Langa, Pablo Galindo Salgado, and Leah Wasser were already on the schedule as keynote speakers, but we’ve now confirmed three more! We are very excited to have the following speakers joining us in Kraków:
William Woodruff is a Member of Technical Staff at Astral, where he works on building high-performance, secure tooling that is modernising the Python developer experience. Prior to Astral, he was an Engineering Director at Trail of Bits, leading high-impact security initiatives across open-source ecosystems.

Marlene Mhangami is a Senior Developer Advocate at Microsoft and GitHub, where she focuses on the cutting edge of Python and AI. As a computer scientist, keynote speaker, and explorer, she is a massive driving force behind community growth across the globe.

Imogen Wright is a Senior Engineer at Amazon EC2, where they focus on making incredibly complex systems behave. Their career spans over two decades of solving high-stakes challenges across theoretical physics, HIV drug resistance, COVID genomics, cloud technologies, and even ad tech!

All of our keynote speakers are some of the most respected leaders in the industry and in their specific fields, and we are privileged to have them join us at EuroPython 2026. We are so pleased to be able to put together such an incredible line up! 🐍💚
⌛ Get Your Ticket Before Prices Increase
We know that many of you have already purchased tickets (thank you!) but a quick reminder to those who have yet to do so: ticket prices will increase on June 26th and our Late Bird prices will apply, so if you’re thinking of coming, it definitely makes sense to secure your ticket before then!
👉 Purchase your tickets today on the EuroPython 2026 website: https://ep2026.europython.eu/tickets/
💻 Remote Ticket Sales
If you are joining us remotely this year, just a heads up that remote sales will start next Monday, 15th June. The tickets will be available to purchase on our website as soon as Monday rolls around!
🎂 25 Years of EuroPython
We are celebrating 25 years of EuroPython this year (I know, we can’t believe it either!), and we have a few fun things planned to make it special, including a chance to win a free ticket - which you can transfer to someone else, if you’ve already got yours!
📜 The Oldest Badge Contest
Are you one of those people who keeps your badges from previous conferences? It might be about to pay off: we will be having a contest to find the Oldest EuroPython Badge amongst all attendees this year! Dig around in your drawers, boxes, attic or other archive and find the oldest EuroPython badge (with your name on it…) that you can. Whoever has the oldest will win the contest!
🎫 Free Ticket Competition: Your EuroPython Experiences
We’re running a competition - open to anyone who has attended EuroPython in the past - who can record a short video telling us about their most impactful EuroPython experience! The competition is open to anyone who has attended EuroPython before, and is really easy to enter. No need for anything very fancy: just record yourself talking and tell us why your particular experience at EuroPython made such an impact on you.
The competition will be closing on June 21st (extended!), so you’ve still got plenty of time to enter.
👉 For the details, see the entry form: https://forms.gle/WNPErwWtpE1oPVhD9
💭 Taking a Trip Down Memory Lane
Finally, we thought you might appreciate a little video we’ve posted on YouTube recently: Jonathan Hartley spoke to us at PyCon US about one of his favourite EuroPython experiences of the past:
🦄 Django Girls Workshop Sign Up
We are sure many of you are already aware of Django Girls and the great work that they do in making Python and Django more accessible to people around the world (often but not only girls!), and we are super pleased to announce that they will be running a workshop at EuroPython 2026 in Kraków!
👉 The workshop is a full day, on 18 July (a sprint day), and you can register on the Django Girls website: https://djangogirls.org/en/krakow2/
🏃♀️ Women in Python 5K Run
On Thursday 16th July there will be a group run with the aim of enabling some friendly networking and friendship building between women in the Python community.
It is open to runners of all experience levels, and will be a nice route around Kraków - along the river and at walking distance from the conference venue. If you are interested, please fill out the form below to help us prepare better (no commitment required - yet!), and we will send details of how to confirm your place closer to the time.
We’d like to thank our sponsor Arm for supporting this run.
👉 Register your interest here: https://forms.gle/bcsBTtNX1crEQhbw8
⭐ On-Site Volunteering
A big thank you to all who responded to our call for on-site volunteers, and we are now considering the applications. We had over 110 applications (far more than last year), and we loved to see applications from countries all over the world! 💚
We are now selecting volunteers, and you will receive notification of the status of your application in the following week (13-19th June). We will contact everyone who applied, even if you were not selected.
Thanks again to all of you - volunteers are the heart of EuroPython and we could not run the conference without you. ✨
👩🏫 Speaker Orientation Workshop
The EuroPython Speaker Orientation ran on the 3rd June 2026, and contained valuable tips from some of the most experienced speakers in our community. The panel spent an hour and a half giving practical advice on preparing talks, creating effective slides, managing nerves, engaging audiences, and handling Q&A sessions.
Cheuk Ting Ho, Rodrigo Girão Serrão, and Sebastian Witowski answered questions from new and returning speakers, sharing insights and lessons from their own conference speaking journeys.
Thank you to our amazing panel and everyone who joined us - we can’t wait to see you in Kraków!
💚 Financial Aid Round Up
This year, we received a record-high 217 financial aid applications across two rounds. We know how much care, hope, and effort goes into every application, and our financial aid team have worked hard to review them all with the attention they deserve.
We’re happy to share that all financial aid decisions have been sent out. With the €35,000 budget provided by the EuroPython Society, we have issued 84 grant offers. We are grateful to be able to support so many members of our community, and sincerely hope that all grantees will be able to join us in Kraków this summer to learn, connect, and celebrate the 25th anniversary of EuroPython.
To everyone who applied but was not offered a grant: we are very sorry for the disappointing news. If we miss you in Kraków, we still very much hope you’ll be part of the conference and connect with us remotely.
📺 EuroPython YouTube Channel
We&aposve been posting a lot of new content over on the EuroPython YouTube Channel, including some fun short interviews from PyCon US:
- Carol Willing talks about her favourite EuroPython moment
- Can you believe that some people have attended this many EuroPython conferences?
- What fun things were planned at PyCon Italia this year?
👉 Subscribe and keep up with our latest videos: https://www.youtube.com/@EuroPythonConference
💬 Last Call for Sponsor Booths
We&aposre down to our last few sponsorship slots with booths! Want to meet the Python community face-to-face at EuroPython 2026? This is your final chance to connect with our thousands of attendees.
👉 Email sponsoring@europython.eu before the slots are gone!
⚙️ Reminder: Rust Summit
Registration is still open for the full-day Rust summit, exploring the intersection of Rust and the Python ecosystem - it is a ‘must-see’ for anyone interested in how Rust is turbocharging Python tooling and Python computational libraries in 2026.
This summit is designed for developers who already possess some practical experience in these topics and are looking to deepen their expertise, share lessons learned, and contribute to the community&aposs collective knowledge.
👉 Register for the Rust Summit: https://ep2026.europython.eu/session/rust-summit-at-europython
🤝 Community Partners
🦬 PyStok
PyStok #83 lands on June 17th at 18:00 at Zmiana Klimatu in Białystok – and free registration is officially live!
Between the "speed dating" networking, JetBrains giveaways, and the legendary "Podlaskie afterparty", it’s the perfect spot to soak up those unique North-East Polish vibes and talk Python and AI with the local crowd.
👉 Grab your spot at https://pystok.org/najblizsze-wydarzenie
📣 Community Outreach
The EuroPython Society has continued our world tour of Python events, and as always, thank you to everyone that came to speak to us!
🇺🇸 PyCon US
Several members of the EuroPython Society were at PyCon US in Long Beach, and we were very happy to have a stand at the conference and meet friends old and new. We know many of you will be joining us in Kraków as well, and we look forward to seeing you again!

👉 For more information about what we got up to PyCon US, check out our post on the EuroPython Society blog: https://europython-society.org/europython-society-at-pycon-us-2026/
🇮🇹 PyCon Italia
The EuroPython Society also had a stand at PyCon Italia, which we shared with the Django Software Foundation, and we were pleased to see such interest in our stickers, which we managed to ‘sell out’ of on the 2nd day of talks! If you want more stickers, you know where to go!

🎁 Sponsor Spotlight
We&aposd like to thank our three Platinum sponsors for supporting EuroPython:
View job openings at ManychatManychat builds AI-powered chat automation for 1M+ creators and brands at real production scale.

Open Source enables Microsoft products and services to bring choice, technology and community to our customers.

Vercel provies Agentic Infrastructure for every app and agent. They are the creators of AI SDK, Next.js, Turborepo, and v0.
👋 Stay Connected
Follow us on social media and subscribe to our newsletter for all the updates:
👉 Sign up for the newsletter: https://blog.europython.eu/portal/signup
- LinkedIn: https://www.linkedin.com/company/europython/
- X/Twitter: https://x.com/europython
- Mastodon: https://fosstodon.org/@europython
- Bluesky: https://bsky.app/profile/europython.eu
- Instagram: https://www.instagram.com/europython/
- YouTube: https://www.youtube.com/@EuroPythonConference
Okay, what a packed edition this one has been! It’s all go here at EuroPython and as you can see, we have so much in store for you. Don’t forget: get your tickets before the prices increase, and we can’t wait to see you really, really soon! 🐍💚
Cheers,
The EuroPython Team
Sign up for EuroPython Blog
The official blog of everything & anything EuroPython! EuroPython 2026 13-19 July, Kraków
No spam. Unsubscribe anytime.
Hugo van Kemenade
I'm delighted to rejoin the Sovereign Tech Fellowship
I’m happy to rejoin the Sovereign Tech Fellowship!
I was one of six participants in the 2025 pilot to pay maintainers of critical open source technologies in the public interest. By all accounts this first cohort was a resounding success, and I’m glad to see the programme continue.
It was wonderful to be part of the inaugural Sovereign Tech Fellowship, and incredibly beneficial to my projects: it gave me the time to focus on releasing Python 3.14 and 3.15 smoothly, to mentor and onboard others, and to support the wider community.
2025 impact #
The 2025 evaluation report covers all six of us and the benefits of the programme at a higher level. Here’s some of the specific things I achieved.
I was happy with how the big Python 3.14.0 release went. This is in part from having a good team to work with, and building on the past, but no doubt also due to being able to focus and invest time thanks to the Fellowship.
On many occasions, having time to dedicate to the role meant I could prioritise things as they occurred. For example, when needing to make expedited releases, I could dedicate time to go through all the necessary prep, and make the release without any stress of fitting it in around a regular job. Similarly, when last-minute problems came up on release day, such as newly-committed code not passing tests, I didn’t need to rush, and could contact the contributor to arrange a fix. Some other release managers had reverted similar changes to let the contributor try again for a later release, but there was less pressure for me and I could wait longer.
I was able to mentor other project members, such as helping onboard the next release manager, and also answer questions for other triagers. I promoted two new triagers in different projects. Other community members sometimes asked me about how to contribute. I attended many community “office hours” meetings and Monthly Conference Organisers' calls to share what’s going on and answer questions, and likewise blogged and shared on social media such as Mastodon, Bluesky and LinkedIn. I was able to attend many conferences and give talks about the upcoming release, and discuss with other attendees what happens with Python releases and the project in general. This all helps improve transparency. I also chaired many monthly Docs Working Group meetings, and attended many other meetings from different projects.
I was able to make many improvements in the release process, through additional automation and testing to remove tedious manual steps. I’ve improved the accessibility of websites visited by tens of millions per month.
I created a triage dashboard that helped us close hundreds of issues, and also complete forgotten backports including security fixes.
I was also able to invest time on non-technical, social, organisational and governance improvements. I’m proud my proposal was accepted to alternate the Language Summit between PyCon US and EuroPython, rather than always being in the US, to improve the diversity of voices of who will shape the future of Python. The 2026 summit will be held at EuroPython and I’m helping organise.
Since 2009, the summit has been a one-day event that takes place at PyCon US before the main conference days. It has also been held at EuroPython twice, in 2010 and 2011. The PSF mission is “to support and facilitate the growth of a diverse and international community of Python programmers”, and not all potential attendees can travel to the US each year. This proposal took a lot of work:
- In November 2024, the core team discussed on Discord the possibility of alternating the summit between PyCon US and EuroPython. People were in favour, but said it would need to be discussed at the summit at PyCon US in May 2025.
- In March 2025, I asked for the topic to be added to the agenda, as I wasn’t attending.
- In May, the discussion took place. The minutes simply said: “Watch out for a Discourse thread to discuss this.”
- In July, during EuroPython, I asked summit attendees what the impression was, and they said people were in favour. I also spoke with the chair of EuroPython Society about the summit requirements, and they said they’d be happy to host us.
- In August, because no Discourse thread had appeared, I opened a proposal to alternate.
- In September, during the Steering Council Q&A at the Core Team Sprint, I asked about next steps. The consensus was for the SC to open a formal poll amongst the core team.
- In October, the SC opened a poll for core team members.
- In November, the poll concluded overwhelmingly in favour of alternating.
- In December, the SC approved my request. I volunteered to help organise the summit and opened discussions with the EuroPython Society to make it happen in 2026.
I had more free time to spend on non-open source things, but also more free time to help the local Python community such as by co-organising two local meetups. One person I nominated became a Fellow of the Python Software Foundation and another of the EuroPython Society, which recognises the importance of community work.
Finally, I enjoyed our monthly Fellowship meetings where the six of us all gave a summary of our last month’s work. Similarly, it was great to meet most of them in person along with people from the Agency at the event to mark the inaugural Sovereign Tech Fellowship cohort and hear the results of the evaluation report.
Arbitrary statistics #
On GitHub:
- Total contributions: 6,642
- Issues created: 90
- PRs created: 901
- Issues closed: 446
- PRs merged: 1,401
- PRs closed: 142
- Total issues involved with: 1,409
- Total PRs involved with: 4,095
- Repositories affected: 409
Made 55 releases:
- 13 of Python 3.14
- 3 of Python 3.15
- 39 of PyPI projects
Started maintaining:
Archived:
Attended eight conferences in Berlin (FOSS Backstage and Design), Bologna (PyCon Italia), Prague (EuroPython), Athens (PyCon Greece), Manchester (PyCon UK), Tallinn (PyCon Estonia), Jyväskylä (PyCon Finland) and Stockholm (PyCon Sweden)
- On a discussion panel at one
- Gave a lightning talk at five
- Announced PyCon Finland at four
- Helped new contributors at sprints at three
- Hosted a barcamp session at one
- Helped organise one by reviewing talks and through promotion
- Volunteered at one
Attended three online conferences:
- March: SustainOSS Virtual Forum
- May: Maintainer Summit
- December: PyLadiesCon
Other events:
- September: Core Team Sprint in Cambridge
- December: Sovereign Tech Agency event in Berlin to mark the inaugural Fellowship cohort
Meetups:
- Co-organised 16 meetups for two groups, one which we restarted in 2025
- Attended 27 meetups of 11 groups in four cities and three countries
- Gave one long talk and four lightning talks
- Organised 12 monthly meetings, chaired 9, attended 10
- Attended two meetings
Published 17 blog posts:
- February: How to delay a Python release
- February: I’m excited to join the Sovereign Tech Fellowship
- February: Improving licence metadata
- March: Free-threaded Python on GitHub Actions
- April: My most used command-line commands
- May: PEPs & Co.
- June: Run coverage on tests
- August: EuroPython 2025: A roundup of writeups
- September: Ready prek go!
- October: Releasing Python 3.14.0
- October: Three times faster with lazy imports
- November: Python Core Sprint 2025
- November: Setting secrets in env vars
- December: Steering Council election
- December: Steering Council results
- December: And now for something completely different
- December: Replacing python-dateutil to remove six
Reported 67 accounts to GitHub for spam/abuse/inauthentic activity.
2026 and beyond #
This time we’re 14 Fellows, and not only maintainers but also community managers and technical writers. It’s great that Python core dev Stan Ulbrych and PSF director Georgi Ker are also joining, and I’m looking forward to meeting the other Sovereign Tech Fellows.
I’m really pleased to again be working with the Sovereign Tech Agency. They’re showing the world some of the ways we can improve open source and critical digital infrastructure, through a range of different programmes. Their success has informed the proposal for an EU Sovereign Tech Fund (EU-STF), and they have also helped shape the European Digital Infrastructure Consortium for digital commons (DC-EDIC), with an EU-STF pilot kicking off later this month which builds on their experience. And it’s good to see the focus on maintenance and long-term sustainability in the brand new EU Open Source Strategy, announced just last week.
And by the way, the Sovereign Tech Agency are currently hiring, check out their open positions.
Header photo by Jan Michalko.
scikit-learn
scikit-learn release 1.9: better numerics, new core functionality
Scikit-learn 1.9 release is out, and it comes with solid improvements to many existing estimators, making them faster, more stable, handling missing values, adding GPU support… The release also enhances the estimator displays in notebooks, and introduces a callback mechanism that opens the door to progress bars or advanced monitoring of convergence.
Improvement: Richer HTML views
The improvements that most will easily view are those on the estimator displays.
Since recent versions, the estimator views displayed in notebooks can show the parameters of the estimators (revealed by clicking on the estimator name). Latest release adds a view of the fitted attribute, as visible below:
HTML display in a notebook, with the fitted attributes visible.
In addition, the ColumnTransformer’s view has been enhanced to help the user understand how features are assembled:
HTML display in a notebook, with the output feature names visible.
A new promise: Callbacks
Scikit-learn 1.9 comes with a callback mechanism, currently experimental. We spent a lot of time designing it so that it enables many different uses: nested tracking of progress (even in parallel computing) on a variety of measures, early stopping…
The release notes come with an example on how to use these callbacks to monitor scores and to display progress bars – a more advance monitoring example.
The logging and progress-bar callbacks in a notebook.
As of today, the callbacks are implemented in logistic regression (with LBFGS solver), the various *SearchCV objects, Pipeline, StandardScaler. The next releases will progressively add callbacks in more and more estimators (this is a place where contributors can help).
Improved statistics and numerics
As users, what we like about scikit-learn routines is that they tend to be “fire-and-forget”, because they reliably run on a huge diversity of inputs: sparse inputs, missing values, different data types. This diversity of inputs is compounded by a diversity of modeling choices: different losses, sample weights…
Each release of scikit-learn extends the toolbox, sometimes by completing the combinatorial of options and data types rather than adding new estimators. Release 1.9 was a real consolidation in this respect:
Tree-based models
-
Native missing-value support in RandomForestRegressor when minimizing the absolute error criterion
-
Support of missing-values for tree-based models monotonic constraints
-
Improved the statistical correctness of fitting with sample weights in HistGradientBoosting, RandomForest and ExtraTree (having exact support of sample weights in complex pipelines is challenging)
Linear models
-
Logistic regression can use natively float32, thus removing memory pressure
-
Multi-Task linear models support fitting on sparse X and sample weights
-
More stable and faster
RidgeCVandRidgeClassifierCV -
Gap safe screening of features for very fast fitting of sparse squared-loss regressors
Other models
-
Sample weight support in minibatch kmeans (a very scalable clustering)
-
Numeric stability of
yeo-johnsonin thepreprocessing.PowerTransformer -
Faster Spectral embedding
Staying up to date with the ecosystem
Scikit-learn can now return sparse arrays, rather than sparse matrices. Indeed, scipy is slowly de-emphasizing sparse matrices, which often surprise users with their behavior that depart from arrays.
Increasing support for GPU
Scikit-learn is increasingly gaining support for optimized compute backends, which enables it, for instance, to run on GPUs. The challenge (and the value) is the incredible diversity of estimators and usecases supported by scikit-learn, and the package is progressively adding backend support in more and more places.
In the 1.9 release, the major features to gain GPU support were:
- Logistic regression and Poisson regression with LBFGS solver
- More metrics (eg average precision score, …)
- Nystroem kernel approximation
See the docs for all details on how to use the compute backends and which estimator support them.
PS: the user experience is currently not as good as with the default compute backend (numpy). But adding and improving GPU support (with the “array API”) is a good place for talented volunteers to help move the project forward.
Acknowledgements
Scikit-learn is the work of many contributors, with people volunteering their time as well as financial sponsors – see the funding page.
June 11, 2026
Talk Python to Me
#551: Stroll Down Startup Lane - 2026
If you've ever been to PyCon, you know one of the best parts of the expo hall is Startup Row, a stretch of booths where early-stage companies built on Python show off what they're creating. But only attendees get to walk that lane, so let's bring it to everyone. In this episode, we stroll down Startup Row together. We kick things off with the organizers, Jason and Shay, who share the program's origin story going back to Paul Graham and the PSF, plus some surprising stats, including two unicorns among the alumni. Then we meet five startups: Tetrix, bringing AI to institutional investing in private markets. Arcjet, security that lives inside your app as an SDK. Phemeral.dev, serverless hosting built for Python web apps. CapiscIO, an identity and authority layer for AI agents. And Pixeltable, a multimodal database from Marcel Kornacker, co-creator of Apache Parquet. See if you can spot the theme running through them all. Let's go for a walk.<br/> <br/> <strong>Episode sponsors</strong><br/> <br/> <a href='https://talkpython.fm/agentfield-page'>AgentField AI</a><br> <a href='https://talkpython.fm/training'>Talk Python Courses</a><br/> <br/> <h2 class="links-heading mb-4">Links from the show</h2> <div><strong>Guests</strong><br/> <strong>Naunidh Bhalla</strong>: <a href="https://www.linkedin.com/in/naunidhbhalla?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>Grant Gittes</strong>: <a href="https://www.linkedin.com/in/grantgittes/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>Marcel Kornacker</strong>: <a href="https://www.linkedin.com/in/marcelkornacker/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>Beon de Nood</strong>: <a href="https://www.linkedin.com/in/beondenood/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>Chinmaya Joshi</strong>: <a href="https://www.linkedin.com/in/cshjoshi/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>David Mytton</strong>: <a href="https://www.linkedin.com/in/davidmytton/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>Shea Tate-Di Donna</strong>: <a href="https://www.linkedin.com/in/sheatatedidonna/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>Jason Rowley</strong>: <a href="https://www.linkedin.com/in/jasondrowley/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>Azul Garza</strong>: <a href="https://github.com/AzulGarza?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>Renée Rosillo</strong>: <a href="https://www.linkedin.com/in/reneerosillo/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <br/> <strong>Tetrix</strong>: <a href="https://www.tetrix.co/?featured_on=talkpython" target="_blank" >tetrix.co</a><br/> <strong>Tetrix Jobs</strong>: <a href="https://www.tetrix.co/careers?featured_on=talkpython" target="_blank" >tetrix.co</a><br/> <strong>Arcjet</strong>: <a href="https://arcjet.com/?featured_on=talkpython" target="_blank" >arcjet.com</a><br/> <strong>Pixeltable</strong>: <a href="https://www.pixeltable.com/?featured_on=talkpython" target="_blank" >pixeltable.com</a><br/> <strong>Phemeral.dev</strong>: <a href="https://phemeral.dev/?featured_on=talkpython" target="_blank" >phemeral.dev</a><br/> <strong>CapiscIO</strong>: <a href="https://capisc.io/?featured_on=talkpython" target="_blank" >capisc.io</a><br/> <br/> <strong>Episode #551 deep-dive</strong>: <a href="https://talkpython.fm/episodes/show/551/stroll-down-startup-lane-2026#takeaways-anchor" target="_blank" >talkpython.fm/551</a><br/> <strong>Episode transcripts</strong>: <a href="https://talkpython.fm/episodes/transcript/551/stroll-down-startup-lane-2026" target="_blank" >talkpython.fm</a><br/> <br/> <strong>Theme Song: Developer Rap</strong><br/> <strong>🥁 Served in a Flask 🎸</strong>: <a href="https://talkpython.fm/flasksong" target="_blank" >talkpython.fm/flasksong</a><br/> <br/> <strong>---== Don't be a stranger ==---</strong><br/> <strong>YouTube</strong>: <a href="https://talkpython.fm/youtube" target="_blank" ><i class="fa-brands fa-youtube"></i> youtube.com/@talkpython</a><br/> <br/> <strong>Bluesky</strong>: <a href="https://bsky.app/profile/talkpython.fm" target="_blank" >@talkpython.fm</a><br/> <strong>Mastodon</strong>: <a href="https://fosstodon.org/web/@talkpython" target="_blank" ><i class="fa-brands fa-mastodon"></i> @talkpython@fosstodon.org</a><br/> <strong>X.com</strong>: <a href="https://x.com/talkpython" target="_blank" ><i class="fa-brands fa-twitter"></i> @talkpython</a><br/> <br/> <strong>Michael on Bluesky</strong>: <a href="https://bsky.app/profile/mkennedy.codes?featured_on=talkpython" target="_blank" >@mkennedy.codes</a><br/> <strong>Michael on Mastodon</strong>: <a href="https://fosstodon.org/web/@mkennedy" target="_blank" ><i class="fa-brands fa-mastodon"></i> @mkennedy@fosstodon.org</a><br/> <strong>Michael on X.com</strong>: <a href="https://x.com/mkennedy?featured_on=talkpython" target="_blank" ><i class="fa-brands fa-twitter"></i> @mkennedy</a><br/></div>
Real Python
Quiz: Serialize Your Data With Python
In this quiz, you’ll test your understanding of Serialize Your Data With Python.
By working through this quiz, you’ll revisit how to choose between textual and binary formats, when to use schemas, and how to apply tools like pickle, json, the csv module, Parquet, and Protocol Buffers safely and effectively.
[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]



Author:
Gael Varoquaux