skip to navigation
skip to content

Planet Python

Last update: June 12, 2026 04:43 PM UTC

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 ]

June 12, 2026 12:00 PM UTC


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.

alt

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.

alt

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!

alt

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:

👉 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!

alt

👉 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!

alt

🎁 Sponsor Spotlight

We&aposd like to thank our three Platinum sponsors for supporting EuroPython:

altView job openings at Manychat

Manychat builds AI-powered chat automation for 1M+ creators and brands at real production scale.


alt

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


alt

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

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

June 12, 2026 09:41 AM UTC


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:

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:

Made 55 releases:

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)

Attended three online conferences:

Other events:

Meetups:

Docs Working Group:

User Success Workgroup:

Published 17 blog posts:

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.

June 12, 2026 07:35 AM UTC


scikit-learn

scikit-learn release 1.9: better numerics, new core functionality

Author: Author IconGael Varoquaux

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 displays showing the fitted attributes 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 displays showing the output feature names 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 barsa more advance monitoring example.

The logging and progress-bar callbacks in a notebook 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

Linear models

Other models

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:

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 12, 2026 12:00 AM UTC

June 11, 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

Package Support

New Features

Optimization

Anti-Bloat

Organizational

Tests

Cleanups

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 11, 2026 10:00 PM UTC


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>

June 11, 2026 08:16 PM UTC


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 ]

June 11, 2026 12:00 PM UTC


PyCharm

Best Python AI Frameworks in 2026

Best Python AI Frameworks in 2026

Whether you’re building chatbots, training computer vision models, or analyzing business data, choosing the right AI framework can make or break your project. Python has become the dominant language for AI and machine learning development, and the ecosystem of frameworks supporting this work has matured significantly.

The right framework choice depends on what you’re building. A production recommendation system has different requirements than a research prototype. A chatbot powered by large language models (LLMs) needs different tools than a fraud detection system analyzing tabular data.

Let’s explore seven essential frameworks and where each excels so you can find the best AI framework for your specific project.

What is an AI framework?

AI frameworks are pre-built libraries and tools that handle the complex mathematics, data structures, and computational operations underlying AI and machine learning models. Rather than implementing neural networks or gradient descent from scratch, AI frameworks provide abstractions that let you focus on model architecture, data preparation, and business logic.

These frameworks generally fall into three categories:

Why do AI frameworks matter? 

AI frameworks dramatically accelerate your development by providing tested, optimized implementations of complex algorithms. They offer strong community support with extensive documentation, tutorials, and troubleshooting resources. They provide production-ready tooling for deployment, monitoring, and scaling. They’re optimized for specific hardware like GPUs and TPUs, delivering performance that would be difficult to achieve with custom implementations.

Open-source vs. commercial AI frameworks

Open-source AI frameworks are the dominant model in AI development today. And they offer compelling advantages, from community-driven innovation for rapid feature development and bug fixes to transparency that enables auditing and algorithm customization. There’s also no vendor lock-in or licensing fees, making them cost-effective for both experimentation and production deployment.

Commercial AI platforms also exist, with AWS SageMaker, Google Vertex AI, and Azure Machine Learning among the prominent examples. However, these platforms often use open-source frameworks underneath rather than competing with them directly. They provide managed infrastructure, automated workflows, and enterprise features on top of tools like TensorFlow and PyTorch.

If you’re thinking open source means they’re unsupported, think again. All seven frameworks below have robust ecosystems, and many are backed by major tech companies. Google supports TensorFlow, Meta backs PyTorch, and organizations like Microsoft contribute significantly to various projects in the ecosystem.

Top Python AI frameworks

These seven frameworks represent the essential toolkit for Python AI development in 2026. Each performs strongly in specific domains, and many developers use multiple frameworks depending on project requirements.

TensorFlow

TensorFlow is an open-source deep learning framework developed by Google for building and deploying machine learning models at enterprise scale. With a 37% market share in data science and machine learning and adoption by 25,000 companies globally, TensorFlow has proven itself in high-stakes production environments.

The framework evolved significantly from TensorFlow 1.x to 2.x, with Keras integration making it far more accessible while maintaining its enterprise-grade capabilities. If you’re building large-scale image recognition systems or natural language processing pipelines, or you need to deploy across web, mobile, and edge devices through TensorFlow Lite and TensorFlow.js, TensorFlow can help.

If you’re just getting started with TensorFlow, follow our step-by-step tutorial on how to train your first TensorFlow model using PyCharm.

Advantages of TensorFlow

Disadvantages of TensorFlow

scikit-learn

scikit-learn is an open-source Python library for classical machine learning, providing simple and efficient tools for classification, regression, clustering, and dimensionality reduction. With adoption by over 16,000 companies worldwide, it’s your essential first stop for structured and tabular data before considering deep learning approaches.

The framework supports a wide range of supervised and unsupervised learning on structured business data, along with feature engineering and data preprocessing pipelines. Companies like J.P. Morgan use scikit-learn extensively for classification tasks and predictive analytics in financial decision-making.

Advantages of scikit-learn

Disadvantages of scikit-learn

PyTorch

PyTorch is an open-source deep learning framework developed by Meta that prioritizes flexibility and a natural Python coding experience. It’s used in approximately 85% of deep learning research papers and has a 55% adoption rate in the research community. From its academic roots, PyTorch has evolved into a production-ready powerhouse.

The framework excels at cutting-edge research and experimentation with novel architectures. It supports natural language processing and generative AI models such as GPT, Llama, and Stable Diffusion, and enables computer vision research with custom model development. Its Pythonic philosophy makes it feel natural if you’re already comfortable with Python, reducing cognitive load and accelerating your development.

Advantages of PyTorch

Disadvantages of PyTorch

Keras

Keras is a high-level deep learning API designed for fast experimentation with neural networks. With over 60,000 GitHub stars and integration as TensorFlow’s default interface, Keras has become synonymous with rapid prototyping and ease of use. The release of Keras 3.0 changed the game by adding multi-backend support for TensorFlow, JAX, and PyTorch.

The framework is ideal for rapidly prototyping neural network architectures, working on educational projects to learn deep learning fundamentals, or tackling deep learning tasks that don’t require low-level customization.

Advantages of Keras

Disadvantages of Keras

LangChain

LangChain is an open-source framework that helps you build applications powered by large language models, providing core components for prompt management, chains, memory, and agent orchestration. It acts as an abstraction layer to easily connect LLMs to external data sources and computational tools. With over 120,000 GitHub stars, the framework has become essential infrastructure for the AI agent revolution.

LangChain is most commonly used for building conversational AI and chatbots with memory and context, retrieval-augmented generation (RAG) systems for enterprise knowledge bases, and multi-agent systems with autonomous workflows.

If you want to go beyond the basics, read our LangChain Python Tutorial: A Complete Guide for 2026. It takes a deeper look at what LangChain offers and walks through real-world use cases for building AI agents in Python.

Advantages of LangChain

Disadvantages of LangChain

Hugging Face

Hugging Face is an open-source platform and library ecosystem for natural language processing and machine learning, with over one million models and 250,000 datasets to power your next project. It’s become a central hub for the AI community, with its Transformers library earning 150,000+ GitHub stars.

The platform is particularly effective at accessing and fine-tuning pre-trained transformer models like BERT, GPT, and Llama, building NLP applications without training models from scratch, and sharing and deploying custom models to the community.

For a practical example, read A Practical Guide to Fine-Tuning and Deploying GPT Models Using Hugging Face Transformers. It walks through using a pre-trained GPT model, fine-tuning it on custom data, and deploying the result with FastAPI.

Advantages of Hugging Face

Disadvantages of Hugging Face

XGBoost

XGBoost is an optimized gradient boosting library designed for speed and performance on structured data. The algorithm continues to dominate machine learning competitions alongside other gradient-boosted decision tree libraries, earning its reputation through battle-tested performance on real-world problems.

You can use the framework for predictive modeling on structured business data, including sales forecasting, risk assessment, and feature importance analysis for model interpretability. Its gradient-boosting approach achieves outstanding precision on structured data, powering reliable insights for business applications.

Advantages of XGBoost

Disadvantages of XGBoost

How to choose an AI framework

Selecting the best AI framework depends on your specific project characteristics, but in practice, the choice is rarely binary. Many successful teams use multiple frameworks together. A common and effective pattern is to use scikit-learn for preprocessing and feature engineering, PyTorch for research and model development, TensorFlow for production deployment, and LangChain for LLM-powered features.

Your decision will likely come down to data type, team expertise, and where your model needs to run. Use this table as a starting point:

Decision factorSuitable Frameworks
By modeling approach and prediction type
Single-value or label prediction (regression or classification using classical ML)scikit-learn, XGBoost
Image and video modeling with neural networksTensorFlow, PyTorch, Keras
Text and NLP with transformer modelsHugging Face, PyTorch, TensorFlow
LLM-powered and agent-based applicationsLangChain, Hugging Face
By level of abstraction and control required
High-level APIs and rapid iterationKeras, scikit-learn
Fine-grained control over training and architecturesPyTorch, TensorFlow
Research-driven experimentation and custom workflowsPyTorch
Managed LLM orchestration and toolingLangChain
By deployment target
Production at scaleTensorFlow
Research/ExperimentationPyTorch
Mobile/EdgeTensorFlow Lite
Web applicationsTensorFlow.js
LLM applicationsLangChain
By task and project objective
Classical prediction and forecasting systemsscikit-learn, XGBoost
Neural network–based modellingTensorFlow, PyTorch, Keras
Building and training novel architecturesPyTorch
Scalable production deploymentTensorFlow
LLM-powered features and workflowsLangChain, Hugging Face

If your choice comes down to PyTorch or TensorFlow, read our dedicated PyTorch vs. TensorFlow: Choosing the Right Framework in 2026 guide, where we compare learning curves, deployment options, and use cases to help you choose the right deep learning framework.

June 11, 2026 11:28 AM UTC


Seth Michael Larson

Linting is important for code review: screen included

Today I was reviewing a pull request for some Python code when I saw a semicolon in the diff. Screenshot provided below, which as we all know is the best way to share text on the internet:

Picture of code with a semicolon (;)

I was just about to leave a comment, but then I scrolled the page a bit and...

Same picture of code, but the dot on top of the semicolon has shifted away revealing it is only a piece of dirt on the screen above a comma (,)

Ah. Time to clean my laptop screen then... 🧼🫧



Thanks for reading ♥ I would love to hear your thoughts! Contact me via Mastodon, Bluesky, or email. Browse the blog archive. Check out my blogroll.



June 11, 2026 12:00 AM UTC

June 10, 2026


Django Weblog

DSF 2026 Fundraising Goals

Django has grown far beyond a web framework. It powers businesses, nonprofits, startups, educational institutions, and critical infrastructure around the world. The Django Software Foundation exists to support that ecosystem, and none of that work is possible without funding. This year, the board set an ambitious new fundraising goal, and I want to be transparent about what we are aiming for and why it matters.

Before talking about where we want to go, it's important to recognize that everything the DSF does today is possible because of the organizations and individuals who already support Django. Their contributions fund the work that keeps Django healthy, secure, and sustainable, and we are deeply grateful for that support.

Our 2026 Goal: $500,000

This year, we are raising our annual fundraising goal from $300,000 to $500,000.

That is a meaningful increase, and it reflects where the foundation needs to be. Our current monthly recurring donations are around $9,000 per month. To reach $500,000 annually, we need to grow that to approximately $15,000 per month.

Reaching this goal will require both new supporters and increased support from existing donors. Doing so will help us maintain the programs the community relies on while creating room for future growth.

What the Money Funds

Before asking for support, it is only fair to explain where the money goes.

The largest line item in our budget is the Django Fellows program. Our three Fellows dedicate their time to triaging tickets, reviewing pull requests, managing releases, handling security issues, and doing the essential work that keeps Django moving forward. Without sustained funding, we cannot maintain this program.

Beyond the Fellows, the DSF:

Taken together, $500,000 in annual funding would allow us to sustain our three Fellows, maintain operational support for the DSF, create a clear path to hiring an Executive Director, and expand our ability to support the Django ecosystem at scale.

Hiring an Executive Director

For most of its history, the DSF has been powered almost entirely by volunteers, with board members handling fundraising, grants, trademarks, and operations on top of their day jobs. That commitment has carried the foundation a long way, but it also limits how much we can take on.

That is why we are working toward hiring an Executive Director this year. An Executive Director would give the foundation dedicated, day-to-day leadership: someone who can build lasting relationships with sponsors, grow our fundraising programs, strengthen support for our volunteers and working groups, and turn the board's long-term plans into steady progress.

We are optimistic about what this role would unlock. With dedicated operational support, the DSF could pursue larger partnerships, launch new programs, and respond more quickly to the community's needs. Reaching our fundraising goal is a key part of making that a reality.

Ways to Support Django

Sponsored Fellow: The Highest-Impact Way to Support Django

This year, the DSF is introducing a Sponsored Fellow corporate membership tier, a new way for organizations to make a direct, visible investment in Django's future.

As a Sponsored Fellow sponsor, your company directly funds one of the Django Fellows who keep the framework running every day. In return, you receive the highest level of recognition the DSF offers. Depending on the partnership, that can include your company's logo and information featured in Django release announcements, recognition through the Fellows' work at conferences and community events, advertising opportunities across DSF communications, and visibility across DSF publications and promotional materials throughout the year.

Django releases reach tens of thousands of developers. The Fellows represent Django at DjangoCon events around the world. If you want your company's name and logo in front of the global Django community, this is the most direct path to get there.

This tier is designed for organizations that depend on Django at scale and want to do more than write a check. It is a partnership, and we will work with you to make sure your sponsorship is visible and meaningful.

To learn more or start a conversation about the Sponsored Fellow tier, reach out through our Contact the DSF page.

Corporate Membership

Corporate membership is a proven way for organizations to support the DSF. Tiers range from Bronze at $2,000 per year up to Platinum at $150,000 per year. Member organizations receive recognition on djangoproject.com, benefits in our community channels, and the knowledge that they are directly funding the framework their teams depend on.

To learn more or get started, visit djangoproject.com/foundation/corporate-membership/.

Individual Donations

Individual donations add up. Whether it is a one-time gift or a small monthly contribution, every bit helps us reach our monthly target and plan ahead with more confidence.

You can donate via our donate page or through Open Collective, which we added last year to make recurring donations easier.

Employer Donation Matching

Many companies offer donation matching programs that can double or even triple the impact of an individual contribution. If your employer has a matching program, the DSF is typically eligible. Check with your HR or finance team and put that benefit to work.

GitHub Sponsors

We have also raised our GitHub Sponsors goal to $15,000 per month to better reflect the level of ongoing support Django needs. We are currently over $9,000 per month, so we are well on our way, but there is still ground to cover. If you already sponsor Django through GitHub, thank you. If you have been thinking about it, now is a great time to start.

Thanks to all our existing sponsors and donors, Django has been able to sustain community initiatives over the past several years.

Spread the Word

If you cannot contribute financially right now, you can still help by spreading the word. Share this post. Mention Django's funding needs the next time someone asks how to give back to open source. Tell your employer about corporate membership.

A Note on Transparency

We publish monthly balance snapshots in our board minutes. The foundation started 2026 with around $222,000 in operating reserves. We take stewardship of those funds seriously, and you should always be able to see where we stand. Those reserves help ensure continuity of operations and provide financial stability for the foundation's ongoing commitments.

Looking Ahead

A significant portion of our funding comes directly from the community through individual donations, memberships, sponsorships, and fundraising campaigns. That ongoing support is one of the clearest signals that Django still matters to the people who build with it every day, and we are deeply grateful for it.

Every Django release, security advisory, ticket review, and mentoring interaction represents countless hours of work from people who care deeply about the framework and community. The DSF exists to make sure that work remains sustainable and that contributors have the support they need to keep Django healthy for everyone who depends on it.

Raising our goal is not about growth for growth's sake. It is about stability, sustainability, and making sure the project, the Fellows, and the broader community have what they need for the years ahead.

We believe $500,000 is achievable. If you have ever benefited from Django, professionally or personally, now is a great time to give back.

Thank you for being part of this community.

June 10, 2026 08:00 PM UTC


Mike Driscoll

How to Get TIFF MetaData with Python

In previous articles on this website, you learned how to extract EXIF data from JPG image files. This week, you will learn how to get similar data from the TIFF image format.

The TIFF format also has its metadata. Pillow provides a similar dictionary for TIFF images in its TiffTags module. If you need a TIFF image, you can use this one, which is a cover from one of the author’s other books on ReportLab:

ReportLab cover

You can create your own TIFF metadata extractor utility by making a new file named tiff_metadata.py and adding this code to it:

# tiff_metadata.py

from PIL import Image
from PIL.TiffTags import TAGS


def get_metadata(image_file_path):
    image = Image.open(image_file_path)
    metadata = {}
    for tag in image.tag.items():
        metadata[TAGS.get(tag[0])] = tag[1]
    return metadata


if __name__ == "__main__":
    metadata = get_metadata("reportlab_cover.tiff")
    print(metadata)

Here you import the TAGS dictionary from the PIL.TiffTags submodule. Then in get_metadata(), you access the tag elements in the image by iterating over the contents of tag.items(). To make that information more readable, you use the TAGS dictionary that you imported.

Here is a sample of the output you will get when you run this code:

{'ImageWidth': (400,),
 'ImageLength': (562,),
 'BitsPerSample': (8, 8, 8),
 'Compression': (1,),
 'PhotometricInterpretation': (2,),
 'FillOrder': (1,),
 'StripOffsets': (82, 130882, 261682, 392482, 523282, 654082),
 'Orientation': (1,),
 'SampleFormat': (1, 1, 1),
 'SamplesPerPixel': (3,),
 'RowsPerStrip': (109,),
 'StripByteCounts': (130800, 130800, 130800, 130800, 130800, 20400),
 'XResolution': ((300, 1),),
 'YResolution': ((300, 1),),
 'PlanarConfiguration': (1,),
 'ResolutionUnit': (2,),
 'ExifIFD': (8,),
 'Software': ('Pixelmator 3.9',),
 'DateTime': ('2020:10:27 12:10:37',),
}

You can see that the value entries above are all tuples. This is because of how the data is returned from the tag data. If you would like a challenge, you can attempt to clean up this data a bit in your version of the metadata extraction utility.

Wrapping Up

EXIF and TIFF metadata are really useful for encoding lots of information in your images. However, most people don’t even know that data is there! Knowing how to access your photo’s metadata allows you to do all kinds of programmatic tasks, such as resizing, sorting files by various parameters, and much more.

You can use Pillow and Python to do all kinds of other image processing, so this is just scratching the surface. Download Pillow today and start learning!

Want to Learn More?

You can learn more about what you can do with Python and Pillow in Mike’s book, Pillow: Image Processing with Python

Purchase at GumroadLeanpub, or Amazon

The post How to Get TIFF MetaData with Python appeared first on Mouse Vs Python.

June 10, 2026 07:15 PM UTC


Python Morsels

Stacks and queues in Python

Use a Python list for stack operations (last-in, first-out) and a deque from the collections module for queue operations (first-in, first-out).

Table of contents

  1. Stacks versus Queues
  2. Stacks in Python
  3. Queues in Python
  4. A deque is a "double-ended queue"
  5. Stack-like and queue-like operations

Stacks versus Queues

In Computer Science, stacks and queues are data structures that are optimized to make it inexpensive to remove either the most recently added item or the least recently added item.

A queue is often called a FIFO data structure: first in, first out.

You can think of a queue as... well, a queue. Or a "line", for Americans like me. The first person to enter a queue will be the first person to reach the front of the queue.

And in programming queues, the first item added will be the first item removed.

A stack is often called a LIFO data structure: last in, first out.

You can think of a stack as a stack of plates... specifically one of those spring-loaded ones from a self-service lunch counter. The last plate that's added to the top of the stack will be the first plate removed from the top of the stack.

And in programming stacks, the last item added will be the first item that's removed.

But how do these terms apply to Python?

Stacks in Python

You can think of Python …

Read the full article: https://www.pythonmorsels.com/stacks-and-queues/

June 10, 2026 04:30 PM UTC


Real Python

Cursor vs Windsurf: Which AI Code Editor Is Best for Python?

AI-powered code editors have moved beyond novelty to become everyday tools for many Python developers. Instead of having to switch between your editor and a separate AI chat, you can use tools like Cursor and Windsurf that bring AI directly into your workflow. As a result, the Cursor vs Windsurf question is a common one for developers deciding which to adopt.

Both Cursor and Windsurf are VS Code forks that import your keybindings, themes, and Python extensions, and both run the same frontier models. They look similar at first but diverge in how they handle changes as you build.

Cursor focuses on control, surfacing AI-generated edits as reviewable diffs and relying on explicit rules to guide agent behavior. Windsurf focuses on flow, applying edits directly in the editor while using broader workspace context, including terminal output, recent edits, and conversation history, to shape its behavior.

In this tutorial, you’ll compare both editors across:

  • AI code completion: How each editor’s completion system behaves and what context it draws on
  • Agentic multi-file editing: How each editor handles tasks involving multiple files, directories, and the terminal
  • Debugging and error correction: How each editor reviews generated code and integrates with your linter

By the end, you’ll have a clear picture of which editor fits your Python workflow. If you’re coming from VS Code, the Python Development in Visual Studio Code tutorial covers the baseline configuration that carries over to both forks.

The table below helps you choose the right editor at a glance:

Use case Cursor Windsurf
You want AI-generated changes shown as reviewable diffs before they’re written to your files, guided by explicit rules
You want edits applied directly as the agent works, using a broader workspace context (terminal output, recent edits, conversation history, and memory)

Cursor is the better fit if you want to review changes before they’re applied. Windsurf is the better fit if you prefer the agent to apply edits directly in your files as it works, drawing on the broader workspace context. To see how this plays out in completion, context management, and debugging, read on.

Get Your Code: Click here to download the free sample code for the resilient HTTP client you’ll build with Cursor and Windsurf in this tutorial.

Take the Quiz: Test your knowledge with our interactive “Cursor vs Windsurf: Which AI Code Editor Is Best for Python?” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Cursor vs Windsurf: Which AI Code Editor Is Best for Python?

Test your understanding of how Cursor and Windsurf compare for Python across AI completion, agentic edits, and debugging workflows.

Metrics Comparison: Cursor vs Windsurf

As you work through the hands-on sections and eventually bring either editor into your own Python projects, the table below gives you a quick reference for some key differences you might expect from each tool:

Metric Cursor Windsurf
IDE support Standalone VS Code fork plus a JetBrains plugin Standalone VS Code fork plus plugins for JetBrains IDEs, Vim, Neovim, Xcode, Visual Studio, and more
AI code completion Fast, line-by-line prediction; strong on single-file typed structures Slower but more structurally aware across interconnected files
Startup performance Faster. Uses lightweight text search that requires no upfront project indexing. Slower initial response. Builds a semantic map of your project structure before it begins.
Debugging performance Identifies and fixes the root cause in one pass Reaches passing tests by working around the root cause over multiple iterations
Resource impact Light. Low background CPU and RAM usage. Heavy. Background indexing can spike local CPU during initial project load.
Billing model Monthly credit pool with unlimited Tab and Auto mode on Pro Daily and weekly usage quotas that refresh automatically on a schedule
Pro plan pricing $20/month $20/month
Ideal project size Small to medium codebases where you already know the structure and can target files manually Large, highly interconnected codebases that benefit from its RAG-based context engine and automatic semantic indexing

In the next sections, you’ll build a resilient HTTP client in Python from scratch and then send the same prompts to both editors to compare their responses.

Getting Started: Installation

Both editors ship as standalone desktop applications that closely match the VS Code experience. On first launch, they offer to import your local VS Code configuration, copying your keybindings, extensions, themes, and settings so your environment carries over with minimal setup.

To follow the hands-on project later in this tutorial, you’ll also want Python 3.12 or later installed on your system. Beyond that, if you need a full VS Code baseline before starting, the Python Development in Visual Studio Code (Setup Guide) course covers the editor setup from scratch.

Both Cursor and Windsurf offer free plans with enough model access to work through this comparison, though keep in mind that free-tier usage is limited and may run out under heavy use.

Installing Cursor

Head to the Cursor download page and download the correct version for your system. During setup, Cursor offers to import your VS Code configuration, including extensions, keybindings, and themes, so your environment carries over with minimal setup.

Once the editor opens, you’re ready to go. You don’t need to configure anything else yet.

If Cursor is new to you, Real Python’s video course on Tips for Using the AI Coding Editor Cursor covers setup, Agent mode, Plan mode, and model selection in a practical context, making the comparisons later in this tutorial easier to follow.

Installing Windsurf

Download Windsurf from the Windsurf download page and run the installer. The VS Code profile import works identically to Cursor’s.

Read the full article at https://realpython.com/cursor-vs-windsurf-python/ »


[ 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 ]

June 10, 2026 02:00 PM UTC


Python GUIs

How to Set Row Background Colors in a QTableView — Use Qt's BackgroundRole to color entire rows based on your data

I have a QTableView table showing some data about connected devices. How can I highlight rows to give a visual indicator of the current status of the device?

When you're working with a QTableView and a custom model, it's common to want to highlight entire rows based on some condition in your data. For example, you might want to color a row blue when a device has a connected status, or red when something has gone wrong.

Understanding How data() Works

In Qt's Model/View architecture, the view calls your model's data() method for every cell in the table — and for each cell, it asks about multiple roles. One of those roles is Qt.BackgroundRole, which tells the view what background color to use for that cell.

The view asks for Qt.BackgroundRole on every single cell, not just one column. So if your data() method returns a color for Qt.BackgroundRole based on the row data (ignoring the column), the color will be applied to every cell in that row.

Let's build a working example.

A Complete Working Example

Here's a full example you can run directly. It creates a QTableView with colored rows based on the PRESENT_STATUS field in each row of data:

python
import sys
from typing import Union

from PyQt6.QtCore import QAbstractTableModel, QModelIndex, Qt
from PyQt6.QtGui import QColor
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView


class TableModel(QAbstractTableModel):

    def __init__(self, data: Union[list, None] = None):
        super().__init__()
        self._data = data or []
        self._hdr = self._gen_hdr_data() if data else []
        self._base_color = {
            "NewConnection": QColor("blue"),
            "Registered": QColor("green"),
        }

    def _gen_hdr_data(self):
        """Build a sorted list of all unique keys across all row dicts."""
        all_keys = set()
        for d in self._data:
            all_keys.update(d.keys())
        return sorted(all_keys)

    def rowCount(self, parent=QModelIndex()):
        return len(self._data)

    def columnCount(self, parent=QModelIndex()):
        return len(self._hdr)

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:
            return self._hdr[section]

    def data(self, index: QModelIndex, role: int):
        if not index.isValid():
            return None

        row_dict = self._data[index.row()]
        state = row_dict.get("PRESENT_STATUS", "")

        if role == Qt.DisplayRole:
            col_key = self._hdr[index.column()]
            value = row_dict.get(col_key, "")
            return str(value) if value else ""

        if role == Qt.BackgroundRole:
            color = self._base_color.get(state)
            if color:
                return color

        return None


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Row Background Colors in QTableView")

        data = [
            {"IP": "192.168.1.10", "PRESENT_STATUS": "NewConnection"},
            {"IP": "192.168.1.108", "FORMER_STATUS": "NewConnection",
             "PRESENT_STATUS": "Registered"},
            {"IP": "192.168.1.50", "PRESENT_STATUS": "Unknown"},
        ]

        self.table = QTableView()
        model = TableModel(data)
        self.table.setModel(model)
        self.setCentralWidget(self.table)


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

The method that Qt calls on the model is called data, so in the example above, the list is stored as self._data (with a leading underscore) to avoid this.

Run this and you'll see three rows. The first row ("NewConnection") has a blue background, the second row ("Registered") has a green background, and the third row ("Unknown") has no special coloring because it isn't in the _base_color dictionary.

QTableView with colored rows based on status values

How Colors are Set on Rows

To understand how the color is being set to the entire row, take a look at the Qt.BackgroundRole section of data():

python
if role == Qt.BackgroundRole:
    color = self._base_color.get(state)
    if color:
        return color

Notice that index.column() isn't used here at all. The color decision is based entirely on the row's PRESENT_STATUS value. Since the view calls data() for every cell in the row — column 0, column 1, column 2, etc. — and each call gets the same color back, the entire row ends up painted.

If you only wanted to color a specific column (say, just the status column), you would add a column check:

python
if role == Qt.BackgroundRole:
    # Only color the PRESENT_STATUS column
    if self._hdr[index.column()] == "PRESENT_STATUS":
        color = self._base_color.get(state)
        if color:
            return color

Making the Text Readable

One thing you'll notice with a dark background color like blue is that the default black text becomes hard to read. You can fix this by also handling Qt.ForegroundRole and returning a light text color when the background is dark:

python
def data(self, index: QModelIndex, role: int):
    if not index.isValid():
        return None

    row_dict = self._data[index.row()]
    state = row_dict.get("PRESENT_STATUS", "")

    if role == Qt.DisplayRole:
        col_key = self._hdr[index.column()]
        value = row_dict.get(col_key, "")
        return str(value) if value else ""

    if role == Qt.BackgroundRole:
        color = self._base_color.get(state)
        if color:
            return color

    if role == Qt.ForegroundRole:
        # If this row has a background color, use white text.
        if state in self._base_color:
            return QColor("white")

    return None

Now blue and green rows will have white text, making everything easy to read.

Updating Colors Dynamically

If your data changes at runtime — for example, a device's status changes from "NewConnection" to "Registered" — you need to tell the view that something has changed so it repaints. You do this by emitting the dataChanged signal:

python
def update_status(self, row, new_status):
    self._data[row]["PRESENT_STATUS"] = new_status
    # Emit dataChanged for the entire row.
    top_left = self.index(row, 0)
    bottom_right = self.index(row, self.columnCount() - 1)
    self.dataChanged.emit(top_left, bottom_right)

This tells the view to re-query data() for every cell in that row, which picks up both the new display text and the new background color. For a deeper look at how signals work to keep your model and view in sync, see Signals, Slots & Events.

Summary

Once you understand how the model's data() method works, coloring entire rows in a QTableView is relatively straightforward. The view asks for each role on every cell, so returning a color from Qt.BackgroundRole based on row-level data — without filtering by column — naturally paints the whole row. Pair that with Qt.ForegroundRole for readable text, and you've got a clean, data-driven way to highlight rows in your table.

To learn more about using QTableView with custom models and data from numpy or pandas, see the QTableView with numpy and pandas tutorial. If you want to add sorting and filtering to your table, take a look at Sorting and Filtering Tables.

For an in-depth guide to building Python GUIs with PyQt6 see my book, Create GUI Applications with Python & Qt6.

June 10, 2026 06:00 AM UTC


Python Insider

Python 3.14.6 and 3.13.14 are now available!

A pair of bug fix releases await your upgrade.

June 10, 2026 12:00 AM UTC


Seth Michael Larson

Are insecure code completions a vulnerability?

Three months ago I saw that PyCharm shipped with a “Full Line Completion” plugin that “uses a local deep learning model to suggest entire lines of code”. These suggestions manifest as whole-line suggestions after you start typing and can be accepted with Tab. Essentially auto-complete for entire lines.

I decide to test this functionality. I started by writing import urllib3, created a new line, and then typed u and received a suggested completion for the line marked below with a dashed border. I was not impressed by the result:

import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

Accepting this line would mean that any insecure requests made with urllib3 would not result in a user-visible warning. I didn't accept this suggestion and then began to instantiate a urllib3.PoolManager and what I feared would come next was confirmed:

import urllib3

urllib3.PoolManager(
    cert_reqs='CERT_NONE',

The suggestion offered to disable certificate verification (CERT_NONE) which would make every request made by the PoolManager susceptible to monster-in-the-middle (MITM) attacks. Accepting this code as-is would mean the program I am writing has a severe vulnerability. If I had accepted the prior suggestion too, then urllib3 would have no chance to warn the user about this mistake prior to productionizing this code.

Clearly something insecure is going on here, but for a CVE to be assigned we have to decide which software component is vulnerable. Does this behavior warrant a CVE at all? I am not sure which is unfortunate, without a security-angle to a bug report companies are less likely to prioritize reports.

I reported this behavior to JetBrains for “Full Line Code Completion” v253.29346.142 and clearly their support staff weren't certain whether this defect was a security vulnerability or not either. When I asked to publish a blog post about this behavior after they confirmed this report wasn’t a “direct security vulnerability” (which I agree with) but then was asked not to publicize my report and referred to PyCharm’s Coordinated Disclosure Policy so... which is it? Security vulnerability or not?

I ended up waiting the 90 days anyway and I didn't hear back with any substantive update from the development team. I double-checked again today using “Full Line Code Completion” v261.24374.152 and the behavior is identical, suggesting the same insecure code for both contexts.

This isn’t meant to be a specific dig at PyCharm or JetBrains, I have no-doubt that examples like this exist in every code generation model available. I don’t think using CVEs for this purpose is appropriate or helpful for users, either. But not prioritizing and addressing this behavior at the source means more work to mitigate the potential for insecure code to be accepted by users who are trusting what is offered to them by their IDE.

What do you think? I am interested in knowing your thoughts about this specific class of issue with code generation models.



Thanks for reading ♥ I would love to hear your thoughts! Contact me via Mastodon, Bluesky, or email. Browse the blog archive. Check out my blogroll.



June 10, 2026 12:00 AM UTC


Armin Ronacher

Gaslighting Openness

I have been a staunch supporter of Open Source for a long time, including experiments in funding it. I’m a true believer in the idea that Open Source always wins in the long run, but not automatically and not quickly. Right now it is being stressed by AI slop, shifting contributor dynamics, the falling cost of producing code, and large companies learning to close doors behind them.

A lot of that battle today is manipulation of the narrative. Opinion makers on social media and in business circles increasingly frame access as irresponsibility. That is why the EU’s DMA matters, even if many people (including myself) reflexively hate EU regulation. Apple’s fight over delayed AI features in Europe is not about Brussels being annoying: it is about whether users can access their own devices and data. The phone is yours, the data is yours, yet Apple decides who may reach it and takes the agency away from you and then tries to make that sound like it is in your interest (supposedly it’s for your safety and security).

The closer you get to the core of AI, the more this shows up. Anthropic has every financial incentive to restrict what people can do with Mythos and Fable, and they wrap those restrictions in safety and (national) security language. Some restrictions may be defensible, but not all of them are. They trained their models on public works, then block Open Source attempts to learn from and distill these systems.

Disliking the EU, China, or any other large government should not make us forget that true democratized access to technology including AI is in all our interest. Some temporary product pain, including delayed Apple AI features, will be worth paying if it keeps gates open. We should not let companies own the narrative that preventing access is in our interest, particularly not as Europeans where the odds are already stacked against us by our underdeveloped capital markets, brain drain and internal fighting.

June 10, 2026 12:00 AM UTC

June 09, 2026


PyCoder’s Weekly

Issue #738: sleep(), Polars Workflows, Iterators, and More (2026-06-09)

#738 – JUNE 9, 2026
View in Browser »

The PyCoder’s Weekly Logo


Python sleep(): How to Add Time Delays to Your Code

Learn how to use Python’s sleep() function to add time delays and pause your code with time.sleep(), decorators, threads, and asyncio.
REAL PYTHON

Libraries for Your Python Polars Workflows

Four excellent libraries for your data science workflow with support for Polars DataFrames
ISABELLA VELÁSQUEZ • Shared by Isabella Velásquez

B2B AI Agent Auth Support

alt

Your users are asking if they can connect their AI agent to your product, but you want to make sure they can do it safely and securely. PropelAuth makes that possible →
PROPELAUTH sponsor

Down the Iterator Rabbit Hole

Following the trail when you have a chain of iterators
STEPHEN GRUPPETTA

PEP 833: Freezing the HTML Simple Repository API (Accepted)

PYTHON.ORG

PEP 800: Solid Bases in the Type System (Final)

PYTHON.ORG

PEP 798: Unpacking in Comprehensions (Final)

PYTHON.ORG

Python 3.15.0b2 Released

PYTHON.ORG

Django Security Releases Issued: 6.0.6 and 5.2.15

DJANGO SOFTWARE FOUNDATION

Articles & Tutorials

olmOCR-2 vs PaddleOCR-VL: Which Extracts PDF Tables Better?

Compare olmOCR-2 and PaddleOCR-VL on a real arXiv PDF with dense technical tables. This article walks through a Python-based OCR workflow, then evaluates how each model handles table detection, runtime, numeric accuracy, merged cells, and multi-tier headers.
KHUYEN TRAN • Shared by Khuyen Tran

Using Typing in Python Leads to Different Sorts of Code

Chris has been moving lots of code from Python 2 to 3 and experimenting with more rigid type hints as he goes along. He’s found that keeping the type checker happy makes him write code in a different way, almost like writing in a second language.
CHRIS SIEBENMANN

Django: Introducing Django-Integrity-Policy

Recently, browsers have added support for the new Integrity-Policy response header (Firefox 145+, Chrome 138+). Adam quickly went to work to build a library that enables your Django project to take advantage of the feature.
ADAM JOHNSON

PSF Strategic Plan 2026 Draft

The Python Software Foundation board has been developing a strategic plan to guide the foundation’s direction over the next five years. The first draft has been released and they’re looking for community feedback.
PYTHON SOFTWARE FOUNDATION

EuroPython 2026 Language Summit Talks

This year’s EuroPython includes a Python Language Summit. This post highlights the talks scheduled for it, including adding Rust capabilities to CPython, an update on incremental garbage collection, and more.
EUROPYTHON.EU

Free Threading Internals: Reference Counting

This article describes how the lifetime of Python objects are tracked using reference counting and how that is effected by the changes brought about by removing the GIL.
VICTOR STINNER

Keep Your Developer Instincts When AI Writes the Code

The promise was less friction. The cost, it turns out, is instinct, a high price to pay. Bob’s answer: add deliberate practice to your routine, and keep the struggle.
BOB BELDERBOS • Shared by Bob Belderbos

How to Use GitHub Copilot Code Review in Pull Requests

Learn how to use GitHub Copilot code review on pull requests for AI-assisted feedback, one-click fixes, and project-specific custom instructions.
REAL PYTHON

Quiz: How to Use GitHub Copilot Code Review in Pull Requests

REAL PYTHON

Parsing XML EXIF From .avif Files (Plus a Rant)

The .avif format tends to result in smaller files, but the EXIF strippers that Andrew was using didn’t support the format, so he wrote his own.
ANDREW STEPHENS

Structuring Your Python Script

Master Python script structure with best practices for shebangs, ordered imports, formatting with Ruff, constants, and a clean entry point.
REAL PYTHON course

Projects & Code

spoof: A Simple HTTP Server for Test Environments

GITHUB.COM/LEXSCA

django-upgrade: Automatically Upgrade Your Django Projects

GITHUB.COM/ADAMCHAINZ

bocpy: Behavior-Oriented Concurrency in Python

GITHUB.COM/MICROSOFT

cohesion: A Tool for Measuring Python Class Cohesion

GITHUB.COM/MSCHWAGER

pypistats.org: PyPI Downloads Analytics Dashboard

GITHUB.COM/PSF

Events

Weekly Real Python Office Hours Q&A (Virtual)

June 10, 2026
REALPYTHON.COM

Python Atlanta

June 11 to June 12, 2026
MEETUP.COM

PyDelhi User Group Meetup

June 13, 2026
MEETUP.COM

DFW Pythoneers 2nd Saturday Teaching Meeting

June 13, 2026
MEETUP.COM

DjangoCologne

June 16, 2026
MEETUP.COM

PyCon Singapore 2026

June 19 to June 22, 2026
PYCON.SG


Happy Pythoning!
This was PyCoder’s Weekly Issue #738.
View in Browser »

alt

[ 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 ]

June 09, 2026 07:30 PM UTC


Python Docs Editorial Board

Meeting Minutes: Jun 9, 2026

Meeting Minutes from Python Docs Editorial Board: Jun 9, 2026

June 09, 2026 07:00 PM UTC


Real Python

Accessing Multiple AI Models With the OpenRouter API

One of the quickest ways to call multiple AI models from a single Python script is to use OpenRouter’s API, which acts as a unified routing layer between your code and multiple AI providers. By the end of this course, you’ll be able to access models from several providers through one unified API.

This convenience matters because the AI ecosystem is highly fragmented: each provider exposes its own API, authentication scheme, rate limits, and model lineup. Working with multiple providers often requires additional setup and integration effort, especially when you want to experiment with different models, compare outputs, or evaluate trade-offs for a specific task.

OpenRouter gives you access to thousands of models from leading providers like OpenAI, Anthropic, Mistral, Google, and Meta. You can switch between them without changing your application code.


[ 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 ]

June 09, 2026 02:00 PM UTC

Quiz: Embeddings and Vector Databases With ChromaDB

In this quiz, you’ll test your understanding of Embeddings and Vector Databases With ChromaDB.

By working through this quiz, you’ll revisit key concepts like vectors, cosine similarity, word and text embeddings, ChromaDB collections, metadata filtering, and retrieval-augmented generation (RAG).


[ 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 ]

June 09, 2026 12:00 PM UTC

Quiz: Accessing Multiple AI Models With the OpenRouter API

In this quiz, you’ll test your understanding of Accessing Multiple AI Models With the OpenRouter API.

By working through this quiz, you’ll revisit how OpenRouter provides a unified routing layer, how to call AI models from a single Python script, how to switch between intelligent routing and a specific model, how to prioritize providers, and how to add model fallbacks for reliability.

It also reinforces how to weigh trade-offs like cost, latency, and quality when you choose a model for your use case.


[ 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 ]

June 09, 2026 12:00 PM UTC


Python Bytes

#483 Thanks Brian

<strong>Topics covered in this episode:</strong><br> <ul> <li><strong>Vulnerability and malware checks in uv</strong></li> <li><strong><a href="https://alexwlchan.net/2026/python-http-with-the-stdlib/?featured_on=pythonbytes">HTTP GET requests with the Python standard library</a></strong></li> <li><strong>Millions of AI agents imperiled by critical vulnerability in open source package</strong></li> <li><strong><a href="https://github.com/Mergifyio/alembic-git-revisions?featured_on=pythonbytes">alembic-git-revisions</a></strong></li> <li><strong>Extras</strong></li> <li><strong>Joke</strong></li> </ul><a href='https://www.youtube.com/watch?v=WIykgbceuVg' style='font-weight: bold;'data-umami-event="Livestream-Past" data-umami-event-episode="483">Watch on YouTube</a><br> <p><strong>About the show</strong></p> <p><strong>Goodbye and Thanks Brian</strong></p> <p>Thanks Calvin for being part of this and future episodes! Also new time for the live show. Thanks Brian for all the hard work over the years.</p> <p><strong>Calvin #1: Vulnerability and malware checks in uv</strong></p> <ul> <li>release just yesterday by Astral https://astral.sh/blog/uv-audit</li> <li><strong><code>uv audit</code></strong> scans dependencies for known vulnerabilities and abandoned packages via the OSV database — runs 4–10x faster than <code>pip-audit</code></li> <li><strong>Malware check</strong> runs on every install/sync, catching actively malicious packages (credential stealers, etc.) before they execute — including ones PyPI quarantined but lockfiles can still reference</li> <li>Enable malware scanning with <code>UV_MALWARE_CHECK=1</code> — it's opt-in and in preview</li> <li>Future roadmap includes a resolver that steers toward vulnerability-free versions and install-time warnings scoped to newly added deps only</li> </ul> <p><strong>Michael #2: <a href="https://alexwlchan.net/2026/python-http-with-the-stdlib/?featured_on=pythonbytes">HTTP GET requests with the Python standard library</a></strong></p> <ul> <li>If you’re doing HTTP in Python, you’re probably using one of three popular libraries: <a href="https://requests.readthedocs.io/en/latest/?featured_on=pythonbytes">requests</a>, <a href="https://github.com/encode/httpx?featured_on=pythonbytes">httpx</a>, or <a href="https://github.com/urllib3/urllib3?featured_on=pythonbytes">urllib3</a>.</li> <li>There have been <a href="https://pythonbytes.fm/episodes/show/476/common-themes">issues with httpx lately</a>.</li> <li><a href="https://github.com/jawah/niquests?featured_on=pythonbytes">Niquest</a> is another option: Drop-in replacement for Requests. Automatic HTTP/1.1, HTTP/2, and HTTP/3. WebSocket, and SSE included.</li> <li>But maybe less is more, especially in the age of agentic AI</li> <li>A good candidate needs two things to be true at once, not one: the <em>used surface</em> is small, and the <em>behavior behind that surface</em> is shallow.</li> </ul> <p><strong>Calvin #3: Millions of AI agents imperiled by critical vulnerability in open source package</strong></p> <ul> <li><strong>"BadHost" (CVE-2026-48710)</strong> is a critical vulnerability in Starlette — the ASGI framework underlying FastAPI — with 325 million weekly downloads; also affects vLLM, LiteLLM, and most MCP server tooling</li> <li><strong>The exploit is trivial</strong>: injecting a single character into an HTTP Host header bypasses path-based authentication, and can lead to credential theft, SSRF, and in some cases remote code execution</li> <li><strong>MCP servers are a prime target</strong> since they store credentials for external services (email, databases, cloud accounts) — exposed data in the wild includes biopharma clinical trial DBs, full mailboxes, HR/PII pipelines, and AWS topology</li> <li><strong>Fix is available</strong> — patch to Starlette 1.0.1 immediately; use the free scanner at mcp-scan.nemesis.services to check if your servers are still running a vulnerable version</li> <li><strong>Open source sustainability footnote</strong>: the maintainer triages near-daily security reports solo, in his free time — most are AI-generated noise, and real ones like this still compete for the same evenings and weekends</li> </ul> <p><strong>Michael #4: <a href="https://github.com/Mergifyio/alembic-git-revisions?featured_on=pythonbytes">alembic-git-revisions</a></strong></p> <ul> <li>By Julien Danjou from <a href="https://mergify.com/?featured_on=pythonbytes">Mergify</a></li> <li>Automatic <a href="https://alembic.sqlalchemy.org/?featured_on=pythonbytes">Alembic</a> migration chaining based on git commit history. No more <code>Multiple head revisions are present for given argument 'head'</code>.</li> <li>See <a href="https://julien.danjou.info/blog/fixing-alembics-multiple-heads-problem-with-git/?featured_on=pythonbytes">the introductory article</a></li> <li>Caused by two migrations landed with the same <code>down_revision</code>, and Alembic doesn’t know which one comes first. The fix is always the same: someone manually edits the migration file to re-chain the revisions.</li> <li>The insight: git already knows the order</li> </ul> <p><strong>Extras</strong></p> <p>Calvin:</p> <ul> <li>GNU <code>make</code> can do pattern matching in the target. Not new at all, mentioned in the 1994-era docs. <code>just</code> and <code>task</code> don’t have this super power on the target name yet. <pre><code>train-%: uv run ./train.py $* --save-hyper-params --overwrite $(TRAIN_ARGS) </code></pre></li> </ul> <p>Michael:</p> <ul> <li>Updated my HTTP client using packages from httpx to <a href="https://github.com/pydantic/httpx2?featured_on=pythonbytes">httpx2</a>: <a href="https://pypi.org/project/listmonk/?featured_on=pythonbytes">listmonk</a>, <a href="https://pypi.org/project/umami-analytics/?featured_on=pythonbytes">umami</a>, and <a href="https://pypi.org/project/memberful/?featured_on=pythonbytes">memberful</a>. For motivation, see <a href="https://www.reddit.com/r/Python/comments/1rl5kuq/anyone_know_whats_up_with_httpx/?featured_on=pythonbytes">this reddit thread</a>.</li> </ul> <p><strong>Joke: <a href="https://x.com/PR0GRAMMERHUM0R/status/2061508112083714478?featured_on=pythonbytes">Accurate</a></strong></p>

June 09, 2026 08:00 AM UTC


Hynek Schlawack

How to Ditch Codecov for Python Projects

Codecov’s unreliability breaking CI on my open source projects has been a constant source of frustration for me for years. I have found a way to enforce coverage over a whole GitHub Actions build matrix that doesn’t rely on third-party services.

June 09, 2026 12:00 AM UTC

June 08, 2026


Real Python

Python 3.15 Hits Feature Freeze and Other News for June 2026

While the Northern Hemisphere warms up for summer, Python 3.15 went the other way with its beta 1 feature freeze 🥶. Since May 7, the list of what will be included in the next release is final. That list includes a brand-new sentinel built-in that finally standardizes a pattern Python developers have been hand-rolling for decades.

And while AI kept writing code, buggy or not, developers also directed it to look for bugs in code that had been sitting untouched for years. The results were hundreds of bug fixes in Python’s C extensions and in Firefox. Meanwhile, in a quieter corner of the ecosystem, Pydantic forked httpx, kicking off one of the more interesting governance stories of the year.

Time to dig into the Python news from the past month!

Join Now: Click here to join the Real Python Newsletter and you’ll never miss another Python tutorial, course, or news update.

Python Releases and PEP Highlights

The 3.15 release of CPython crossed from alpha into beta, which means its feature set is now frozen, and the Steering Council cleared out a backlog of proposals before the gate closed. Two of those changes will touch the code you write every day.

Beta 1 Marks the 3.15 Feature Freeze

Last month, the eighth and final alpha rolled out as the runway to the beta phase. With Python 3.15.0b1 on May 7 came the feature freeze, which means that from here until the final release of 3.15, the core team works only on bug fixes and polishing.

That makes the beta releases a good moment to step back and look at the headline features of 3.15, which are now locked:

The JIT compiler also gets faster, with the beta announcement citing an 8–9 percent geometric-mean improvement on x86-64 Linux. If you’ve been putting off testing your code against 3.15, then now is the time to get started! The API surface won’t shift under you anymore, and your feedback will help catch regressions before the release candidate phase.

Note: Beta builds are for testing, not production. Install the pre-release version, run your test suite against 3.15, and report anything that breaks while there’s still time to fix it before the release candidate.

The first round of improvements already landed with beta 2 on June 2, and the next big checkpoint is the release candidate phase on August 4, with the final release expected, as usual, this fall.

A Built-in sentinel Lands in Python 3.15

Here’s the new feature that you’ll likely want to reach for. If you’ve ever needed to tell the difference between a caller passing None and a caller passing nothing at all, then you’ve probably written something like this:

Language: Python
_MISSING = object()

def update(value=_MISSING):
    if value is _MISSING:
        ...  # No value was provided

It works, but it has rough edges. The repr() is an unhelpful <object object at 0x7f...>, the marker can’t be used cleanly in type annotations, and its identity doesn’t survive copying or pickling. PEP 661 replaces the idiom with a new sentinel built-in:

Language: Python
MISSING = sentinel("MISSING")

def update(value: int | MISSING = MISSING) -> None:
    if value is MISSING:
        ...  # No value was provided

The signature is sentinel(name, /, *, repr=None), and the result is a unique truthy object whose default repr() is the name you gave it, so MISSING shows up as MISSING in tracebacks instead of a memory address.

Note: Sentinels and None solve related but different problems. If you’re still fuzzy on when None is the right tool, then Real Python’s guide to Python’s None is worth revisiting.

Because the sentinel is its own type, you can drop it straight into annotations like int | MISSING without reaching for Literal. The PEP was first submitted back in 2021, so it’s satisfying to see it cross the finish line.

PEP 829 Graduates From Draft to Accepted

Last month’s roundup featured PEP 829 while it was still a draft. It’s since been accepted for Python 3.15, so the change is now official.

As a quick recap, .pth files in your site-packages directory can do two things:

  1. Extend sys.path
  2. Run arbitrary code through import lines that Python feeds directly to exec() at startup

Read the full article at https://realpython.com/python-news-june-2026/ »


[ 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 ]

June 08, 2026 02:00 PM UTC