skip to navigation
skip to content

Planet Python

Last update: April 17, 2026 04:43 PM UTC

April 17, 2026


Mike Driscoll

Textual – An Intro to DOM Queries (Part I)

In this article, you will learn how to query the DOM in Textual. You will discover that the DOM keeps track of all the widgets in your application. By running queries against the DOM, you can find widgets quickly and update them, too.

You will be learning the following topics related to the DOM:

You will learn more in the second part of this series next week!

You will soon see the value of working with DOM queries and the power that these queries give you. Let’s get started!

The Query One Method

You will find the query_one() method throughout the Textual documentation and many Textual applications on GitHub. You may use query_one() to retrieve a single widget that matches a CSS selector or a widget type.

You can pass in up to two parameters to query_one():

If you pass both, pass the CSS selector first, with the widget type as the second parameter.

Try some of this out. Open up your Python editor and create a file named query_input.py. Then enter this code in it:

# query_input.py

from textual.app import App, ComposeResult
from textual.widgets import Button, Input


class QueryInput(App):

    def compose(self) -> ComposeResult:
        yield Input()
        yield Button("Update Input")

    def on_button_pressed(self) -> None:
        input_widget = self.query_one(Input)
        new_string = f"You entered: {input_widget.value}"
        input_widget.value = new_string


if __name__ == "__main__":
    app = QueryInput()
    app.run()

Your code creates an Input and a Button widget. Enter some text in the Input widget and press the button. Your on_button_pressed() method will get called. You call query_one() and pass it an Input widget. Then, you update the returned Input widget’s value with a new string.

Here is what the application might look like:

Now, you will try writing a new piece of code where you use query_one() with a CSS selector. Create a new file called query_one_same_ids.py and use this code:

# query_one_same_ids.py

from textual.app import App, ComposeResult
from textual.widgets import Button, Label


class QueryApp(App):

    def compose(self) -> ComposeResult:
        yield Label("Press a button", id="label")
        yield Button("Test", id="button")

    def on_button_pressed(self) -> None:
        widget = self.query_one("#label")
        widget.update("You pressed the button!")


if __name__ == "__main__":
    app = QueryApp()
    app.run()

In this example, you create two widgets with different IDs. Then you use query_one() to select the Label widget and update its text.

If you call query_one() and there are no matches, you will get a NoMatches exception. On the other hand, if there is more than one match, the method will return the first item that does match.

What will the following code do if you put it in your example above?

self.query_one(”#label”, Button)

If you guessed that Textual will raise an exception, you should congratulate yourself. You have good intuition! If the widget matches the CSS selector but not the widget type, then you will get a WrongType exception raised.

Textual Queries

Textual has more than one way to query the DOM. You may also use the query() method, which you can use to query or find multiple widgets. When you call query(), it will return a DOMQuery object, which behaves as a list-like container of widgets.

You can see how this works by writing some code. Create a new Python file named query_all.py and add this code to it:

# query_all.py

from textual.app import App, ComposeResult
from textual.widgets import Button, Label


class QueryApp(App):

    def compose(self) -> ComposeResult:
        yield Label("Press a button", id="label")
        yield Button("Test", id="button")

    def on_button_pressed(self) -> None:
        widgets = self.query()
        s = ""
        for widget in widgets:
            s += f"{widget}\n"
        label = self.query_one("#label")
        label.update(s)


if __name__ == "__main__":
    app = QueryApp()
    app.run()

The idea is to get all the widgets in your application and print them out. Of course, you can’t print out anything when your terminal application is blocking stdout, so instead, you create a string of widgets separated by new lines and update the Label widget.

Here is an example of what you might get if you run the code and press the button on your machine:

You might be surprised by that output. Perhaps you thought you would only see a Label and a Button widget in that list? If so, you forgot that a Screen widget is always lurking in the background. But there are also two more: a ToastRack and a Tooltip widget. These come with all your applications. The ToastRack positions Toast widgets, which you use to display a notification message. A Tooltip is a message that appears when you hover your mouse over a widget.

You do not need to know more about those extra widgets now.

Also note that all query methods can be used on both the App and Widget subclasses, which is very handy.

Using Selectors

You can use CSS selectors with query() in much the same way as you can with query_one(). The difference, of course, is that query() always returns an iterable DOMObject.

Let’s pretend you want to get all the Button widgets in your application and iterate over them. Create a new Python script called query_button.py with this code:

# query_buttons.py

from textual.app import App, ComposeResult
from textual.widgets import Button, Label


class QueryApp(App):

    def compose(self) -> ComposeResult:
        yield Label("Press a button", id="label")
        yield Button("One", id="one")
        yield Button("Two", id="two")
        yield Button("Three")

    def on_button_pressed(self) -> None:
        s = ""
        for widget in self.query("Button"):
            s += f"{widget}\n"
        label = self.query_one("#label")
        label.update(s)


if __name__ == "__main__":
    app = QueryApp()
    app.run()

Here you are passing in a string, “Button”, to query(). If using query_one, you would use the Button type directly. Regardless, when you run this code and press the button, you will see the following:

That worked great! This time, you queried the DOM and returned all the Button widgets in your application.

What if you wanted to find all the disabled buttons in your code? You can disable widgets using the disabled style flag or the CSS attribute. To find those widgets, you would update the query like this: widgets = self.query("Button.disabled").

Results

The query objects in Textual also provide a results() method that you can use as an alternative way of iterating over the widgets. For example, you can use results() to rewrite the query above that would retrieve all the disabled buttons to be something like this:

widgets = self.query(".disabled").results(Button)
s = ""
for widget in widgets:
    s += f"{widget}\n"

This code combines the last example query with the last full code example. Although this latter version is more verbose, you might find it easier to read than the original query for disabled widgets.

Another benefit of using results() is that Python type checkers, such as Mypy, can use it to determine the widget type in the loop. When you do not use results(), then Mypy will only know that you are looping over a Widget object, rather than a Button object.

Wrapping Up

You learned the basics of using Textual’s DOM query methods in this article. You can use these query methods to access one or more widgets in your user interface.

Specifically, you learned about the following:

Textual is a great way to create a user interface with Python. You should check it out today!

Learn More

Want to learn more about Textual? Check out my book, Creating TUI Applications with Textual and Python:

The post Textual – An Intro to DOM Queries (Part I) appeared first on Mouse Vs Python.

April 17, 2026 12:57 PM UTC


Real Python

The Real Python Podcast – Episode #291: Reassessing the LLM Landscape & Summoning Ghosts

What are the current techniques being employed to improve the performance of LLM-based systems? How is the industry shifting from post-training towards context engineering and multi-agent orchestration? This week on the show, Jodie Burchell, data scientist and Python Advocacy Team Lead at JetBrains, returns to discuss the current AI coding landscape.


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

April 17, 2026 12:00 PM UTC

Quiz: Working With Python Virtual Environments

Test your understanding of the Working With Python Virtual Environments video course.

You’ll revisit why virtual environments matter, how to create and activate them, and how to install and manage packages inside an isolated Python environment.


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

April 17, 2026 12:00 PM UTC

April 16, 2026


Talk Python to Me

#545: OWASP Top 10 (2025 List) for Python Devs

The OWASP Top 10 just got a fresh update, and there are some big changes: supply chain attacks, exceptional condition handling, and more. Tanya Janca is back on Talk Python to walk us through every single one of them. And we're not just talking theory, we're going to turn Claude Code loose on a real open source project and see what it finds. Let's do it.<br/> <br/> <strong>Episode sponsors</strong><br/> <br/> <a href='https://talkpython.fm/temporal-replay'>Temporal</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>DevSec Station Podcast</strong>: <a href="https://www.devsecstation.com/?featured_on=talkpython" target="_blank" >www.devsecstation.com</a><br/> <strong>SheHacksPurple Newsletter</strong>: <a href="https://newsletter.shehackspurple.ca/?featured_on=talkpython" target="_blank" >newsletter.shehackspurple.ca</a><br/> <strong>owasp.org</strong>: <a href="https://owasp.org?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>owasp.org/Top10/2025</strong>: <a href="https://owasp.org/Top10/2025/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>from here</strong>: <a href="https://github.com/awesome-selfhosted/awesome-selfhosted?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>Kinto</strong>: <a href="https://github.com/Kinto/kinto?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>A01:2025 - Broken Access Control</strong>: <a href="https://owasp.org/Top10/2025/A01_2025-Broken_Access_Control/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>A02:2025 - SecuA02 Security Misconfiguration</strong>: <a href="https://owasp.org/Top10/2025/A02_2025-Security_Misconfiguration/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>ASP.NET</strong>: <a href="https://ASP.NET?featured_on=talkpython" target="_blank" >ASP.NET</a><br/> <strong>A03:2025 - Software Supply Chain Failures</strong>: <a href="https://owasp.org/Top10/2025/A03_2025-Software_Supply_Chain_Failures/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>A04:2025 - Cryptographic Failures</strong>: <a href="https://owasp.org/Top10/2025/A04_2025-Cryptographic_Failures/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>A05:2025 - Injection</strong>: <a href="https://owasp.org/Top10/2025/A05_2025-Injection/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>A06:2025 - Insecure Design</strong>: <a href="https://owasp.org/Top10/2025/A06_2025-Insecure_Design/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>A07:2025 - Authentication Failures</strong>: <a href="https://owasp.org/Top10/2025/A07_2025-Authentication_Failures/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>A08:2025 - Software or Data Integrity Failures</strong>: <a href="https://owasp.org/Top10/2025/A08_2025-Software_or_Data_Integrity_Failures/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>A09:2025 - Security Logging and Alerting Failures</strong>: <a href="https://owasp.org/Top10/2025/A09_2025-Security_Logging_and_Alerting_Failures/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>A10 Mishandling of Exceptional Conditions</strong>: <a href="https://owasp.org/Top10/2025/A10_2025-Mishandling_of_Exceptional_Conditions/?featured_on=talkpython" target="_blank" >owasp.org</a><br/> <strong>https://github.com/KeygraphHQ/shannon</strong>: <a href="https://github.com/KeygraphHQ/shannon?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>anthropic.com/news/mozilla-firefox-security</strong>: <a href="https://www.anthropic.com/news/mozilla-firefox-security?featured_on=talkpython" target="_blank" >www.anthropic.com</a><br/> <strong>generalpurpose.com/the-distillation/claude-mythos-what-it-means-for-your-business</strong>: <a href="https://www.generalpurpose.com/the-distillation/claude-mythos-what-it-means-for-your-business?featured_on=talkpython" target="_blank" >www.generalpurpose.com</a><br/> <strong>Python Example Concepts</strong>: <a href="https://blobs.talkpython.fm/owasp-top-10-2025-python-example-concepts.html" target="_blank" >blobs.talkpython.fm</a><br/> <br/> <strong>Watch this episode on YouTube</strong>: <a href="https://www.youtube.com/watch?v=ffid3jWA0JE" target="_blank" >youtube.com</a><br/> <strong>Episode #545 deep-dive</strong>: <a href="https://talkpython.fm/episodes/show/545/owasp-top-10-2025-list-for-python-devs#takeaways-anchor" target="_blank" >talkpython.fm/545</a><br/> <strong>Episode transcripts</strong>: <a href="https://talkpython.fm/episodes/transcript/545/owasp-top-10-2025-list-for-python-devs" 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>

April 16, 2026 08:24 PM UTC


Django Weblog

New Technical Governance - request for community feedback

Hello Django community,

The Steering Council is excited to share our proposed new technical governance and ask for your feedback. Last year we suspended the formal voting process of the Steering Council. The updates we’re proposing would bring how we’ve been operating into alignment with the written governance.

From the motivation section:

This is a revisitation of Django's technical governance in which a simplification and reduction was made to make it more approachable to more people. The goals of these changes are the following:

  • Make it easier to enact our governance.
  • Make it easier for others to understand our governance.
  • Make the governance more flexible, allowing more action with less procedure.

You can read DEP 0019 here.

Adoption plan

The goal is to have this governance accepted and in place by 2026-07-01. Our timeline is as follows, but may change depending on feedback.

What we need from you

We would like to know if we are achieving our goals with this document. For example, do you feel that this makes our governance easier to understand, do you feel like you have a better understanding of who is eligible to run for the Steering Council, is it clear how Django operates from a process perspective?

Beyond that, if you have other feedback around the changes, please share it. This has gone through a high degree of review from the Steering Council and Board over the past 5 months, but that doesn’t mean there aren't areas where it can be improved.

Anyone can participate in this process on the Forum thread here.

April 16, 2026 07:59 PM UTC

PyCharm &amp; Django annual fundraiser

For another year, we are thrilled to partner with our friends at JetBrains on the annual "Buy PyCharm, Support Django" campaign. This is the first of two fundraisers we're running with JetBrains this year, and it's one of the most impactful ways the community can support the Django Software Foundation.

"JetBrains is a cornerstone in the Django community, consistently helping us understand our evolving landscape. Their annual survey provides invaluable insights into the community's needs, trends, and tools, ensuring we stay on the pulse of what matters most."

Jeff Triplett, President, Django Software Foundation

Your support of this campaign helps fund key initiatives such as:

How the campaign works

From today to May 1, when you purchase PyCharm at a 30% discount through our special campaign link, JetBrains will donate an equal amount to the Django Software Foundation. You get a professional IDE that's trusted by Django developers worldwide, and the DSF receives a matched contribution.

Get 30% off PyCharm, Support Django

Thank you, JetBrains

Beyond this campaign, JetBrains contributes to the Django ecosystem in ways that are easy to overlook but hard to overstate. Their Django Developers Survey, State of Django report, and broader Python Developers Survey give the entire community a clearer picture of where Django and Python are heading each year.

"JetBrains is one of our most generous fundraising partners year after year, helping us sustain and grow the Django ecosystem. We deeply appreciate their commitment, leadership, and collaboration."

Thank you to JetBrains for another year of partnership, and thank you to everyone who participates in this campaign. Together, we can ensure the continued success and growth of the framework we all rely on.

Other ways to donate

If you would like to donate in another way, especially if you are already a PyCharm customer, here are other ways to donate to the DSF:

April 16, 2026 05:45 PM UTC


Python Software Foundation

Announcing Python Software Foundation Fellow Members for Q4 2025! 🎉

The PSF is pleased to announce its fourth batch of PSF Fellows for 2025! Let us welcome the new PSF Fellows for Q4! The following people continue to do amazing things for the Python community:

Chris Brousseau

Website, LinkedIn, GitHub, Mastodon, X, PyBay, PyBay GitHub

Dave Forgac

Website, Mastodon, GitHub, LinkedIn

Inessa Pawson

GitHub, LinkedIn

James Abel

Website, LinkedIn, GitHub, Bluesky

Karen Dalton

LinkedIn

Mia Bajić

Tatiana Andrea Delgadillo Garzofino

Website, GitHub, LinkedIn, Instagram

Thank you for your continued contributions. We have added you to our Fellows Roster.

The above members help support the Python ecosystem by being phenomenal leaders, sustaining the growth of the Python scientific community, maintaining virtual Python communities, maintaining Python libraries, creating educational material, organizing Python events and conferences, starting Python communities in local regions, and overall being great mentors in our community. Each of them continues to help make Python more accessible around the world. To learn more about the new Fellow members, check out their links above.

Let's continue recognizing Pythonistas all over the world for their impact on our community. The criteria for Fellow members is available on our PSF Fellow Membership page. If you would like to nominate someone to be a PSF Fellow, please send a description of their Python accomplishments and their email address to psf-fellow at python.org. We are accepting nominations for Quarter 1 of 2026 through February 20th, 2026.

Are you a PSF Fellow and want to help the Work Group review nominations? Contact us at psf-fellow at python.org.

April 16, 2026 02:45 PM UTC


Real Python

Quiz: Welcome to Real Python!

In this quiz, you’ll test your understanding of Welcome to Real Python!

By working through this quiz, you’ll revisit key platform features like video courses, written tutorials, interactive quizzes, Learning Paths, and the Slack community.

You’ll also review strategies for learning effectively, including immersion, daily progress, and building a habit.


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

April 16, 2026 12:00 PM UTC

Learning Path: Python Game Development

Build Python games from command-line projects to 2D graphical games with turtle, Tkinter, Pygame, and Arcade.


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

April 16, 2026 12:00 PM UTC


death and gravity

Learn Python object-oriented programming with Raymond Hettinger

💢 There must be a better way.

Raymond Hettinger is a Python core developer. Even if you haven't heard of him, you've definitely used his work, bangers such as sorted(), enumerate(), collections, itertools, @lru_cache, and many others. Over the years, he's held lots of great talks, some of them on effective object-oriented programming in Python.

The talks in this article had a huge impact on my development as a software engineer, are some of the best I've heard, and are the single most important reason you should not be afraid of inheritance anymore; don't trust me, look at the YouTube comments!

Note

This list is only to whet your appetite – to get the most out of it, watch the talks in full; besides being a great teacher, Raymond is quite the entertainer, too.

Contents

The Art of Subclassing #

Subclassing can just be viewed as a technique for code reuse.

The Art of Subclassing (2012) is about use cases, principles, and design patterns for inheritance, with examples from the standard library.

The point is to unlearn the animal examples – instead of the classic hierachical view where subclasses are specializations of the parent, there's an operational view where:

This view brings clarity to other related topics:

Finally, a quote about the standard library:

The best way to become a better Python programmer is to spend some time reading the source code written by great Python programmers.

Sounds familiar?

Learn by reading code: Python standard library design decisions explained

Python's Class Development Toolkit #

Each user will stretch your code in different ways.

Python's Class Development Toolkit (2013) is a hands-on exercise: build a single class, encounter common problems users have with it, come up with solutions, repeat.

Use the lean startup methodology to build an advanced circle analytic toolkit with:

Super considered super! #

Super considered super! (2015) goes deep into cooperative multiple inheritance, problems you might encounter, and how to fix them.

The main point is that just like how self refers not to you, but to you or your children, super() does not call your ancestors, but your children's ancestors – it may even call a class that isn't defined yet.

This allows you to change the inheritance chain after the fact; examples include a form of dependency injection, overriding parent behavior without changing its code, and an OrderedCounter class based on Counter and OrderedDict.

The article by the same name is worth a read too, and has different examples.

Object Oriented Programming from scratch (four times) #

Object Oriented Programming from scratch (four times) (2020) does exactly that, each time giving a new insight into what, how, and why we use objects in Python.

The first part shows OOP emerge naturally from the need for more namespaces, by iteratively improving a script that emulates dictionaries.

The second one covers the history of moving from a huge pile of data and functions to:

Sounds familiar?

When to use classes in Python? When your functions take the same arguments
When to use classes in Python? When you repeat similar sets of functions

The third part explains the mechanics of objects via ChainMap, tl;dr:

ChainMap(instance_dict, class_dict, parent_class_dict, ...)

The fourth part highlights how OOP naturally expresses entities and relationships by looking the data model of a Twitter clone and the syntax tree of a compiler.

Beyond PEP 8 – Best practices for beautiful intelligible code #

Well factored code looks like business logic.

Beyond PEP 8 – Best practices for beautiful intelligible code (2015) (code) is about how excessive focus on following PEP 8 can lead to code that is beautiful, but bad, since it distracts from the beauty that really matters:

Pythonic
coding beautifully in harmony with the language to get the maximum benefits from Python

Transform a bad API into a good one using an adapter class and stuff like:

And remember:

If you don't transform bad APIs into Pythonic APIs, you're a fool!

Bonus: The Mental Game of Python #

The computer gives us words that do things; what daddy does is make new words to make computers easier to use.3

The Mental Game of Python (2019) is not just about programming, but about problem solving strategies. The most relevant one for OOP is: build classes independently and let inheritance discover itself; this is because:

A lot of real world problems aren't tic-tac-toe problems, where you can see to the end; they are chess problems, where you can't.

For a more meta discussion of this idea, check out Repeat yourself, do more than one thing, and rewrite everything by tef; it should be considered a classic at this point.

Parting Raymond Hettinger quote:

I came to here you to show you how to chunk, and how to stack one chunk on top of the other, and this is a way to reduce your cognitive load and manage complexity; it is the core of our craft; it's what we're here to do.


Anyway, that's it for now. :)

Who learned something new today? Share it with others!

Want to know when new articles come out? Subscribe here to get new stuff straight to your inbox!

  1. But remember it's a principle, not a law, violations are fine – you may only want substitutability in some places (e.g. contructors are often not substitutable). [return]

  2. ...unless you use double underscores. [return]

  3. In my opinion, this quote alone is reason enough to watch the talk. [return]

April 16, 2026 09:00 AM UTC


Bruno Ponne / Coding The Past

Exploring the MET API with Python - Francisco Goya's Artworks

The act of painting is about one heart telling another heart where he found salvation.

— Francisco Goya


Francisco Goya is one of my favorite artists. His work has a beautiful darkness that tells a lot about his experience in his time. In this post, we’ll dive into his world using the Metropolitan Museum of Art (MET) application programming interface (API), which gives developers access to data on hundreds of thousands of artworks.


You will learn how to interact with the MET API using Python. We will journey through the process of making HTTP requests, parsing the returned JSON data into a structured pandas DataFrame, and exploring the collection to extract meaningful insights about Goya’s work.


1. Requesting data from the API


We begin by importing the requests library, which allows us to send HTTP requests to the MET REST API in Python. We’ll query the search endpoint to find Goya’s paintings. In API terms, an endpoint is a specific URL used to access a particular resource.


The MET API has four endpoints starting with “https://collectionapi.metmuseum.org/”:


You can find more details about each endpoint and its functionality in the official MET API documentation.

tips_and_updates  
A REST (Representational State Transfer) API is a set of rules used to communicate between your computer and the MET server using HTTP methods and endpoints. Note that many APIs require authentication; however, the MET API is public and does not require an API key.


content_copy Copy

import requests
import pandas as pd

search_query = "https://collectionapi.metmuseum.org/public/collection/v1/search?hasImages=true&q=Francisco Goya"

response = requests.get(search_query)
search_data = response.json()

print(f"Found {search_data['total']} artworks for Francisco Goya.")


API endpoints can be followed by query parameters that refine our search. In the example above, hasImages=true filters for objects with images, and q specifies our search term—in this case, the artist’s name.


The requests library contains a method called get(), which we use to send our request to the API, passing our endpoint saved in the string search_query.


The resulting response object can then be parsed into a JSON structure using the .json() method.


2. Converting JSON to a list of painting ids


While JSON is the standard for data exchange, working with raw JSON can be cumbersome for direct data analysis. In Python, you can think of JSON as a dictionary of keys and values. These values can themselves be other dictionaries, lists, numbers, strings, or booleans. By printing the search_data object, we can see that it’s a dictionary containing two main keys:


To retrieve the list of IDs associated with the key “objectIDs” we use the standard dictionary notation search_data["objectIDs"] and save it to the variable goya_ids.


content_copy Copy

print(search_data)
goya_ids = search_data["objectIDs"]


3. Getting the details of each of Goya’s works


To retrieve details for each artwork — such as its title, date, and thematic tags — we need to iterate through the list of IDs and send a request to the /objects/{objectID} endpoint for each item. We implement this using a for loop that repeats the request for each artwork.


(Note: Depending on the number of results, fetching these details can take a few minutes. We use time.sleep(1) to respect the API’s rate limits and avoid being blocked.)


content_copy Copy

import time

all_objects_data = []


for object_id in goya_ids:
    try:
        obj_response = requests.get(f"https://collectionapi.metmuseum.org/public/collection/v1/objects/{object_id}")
        obj_response.raise_for_status() 
        all_objects_data.append(obj_response.json())
    except requests.exceptions.RequestException as e:
        print(f"Error for object ID {object_id}: {e}")
    
    time.sleep(1) # Respect the API, one request per second to be safe

# Convert the gathered data to a DataFrame
goya_df = pd.json_normalize(all_objects_data)

# Filter only Goya works
goya_df = goya_df[goya_df['artistDisplayName'].str.contains('Goya', na=False)]


We use a try-except block to ensure the loop continues even if a specific object ID fails to load. We also log any errors to help with debugging.


Finally, we convert the collected data into a Pandas DataFrame using pd.json_normalize. Since a broad search might return works about Goya or mentioning him in metadata, we filter the DataFrame to ensure the artistDisplayName actually contains “Goya.”


The resulting DataFrame contains intriguing data about each of his works, including name, year when the painting or drawing was started and finished, descriptive tags and dimensions, among other information. Feel free to explore it. We will continue working with the descriptive tags in the next steps.


4. Flattening nested JSON data


For keys whose values are lists or other dictionaries, the resulting columns will contain those respective objects. This happens, for example, with the tags column. When you have nested elements like this, you can “flatten” them into a tabular format.


JSON structure

JSON data structure


Flattening an element changes the granularity of the data. Whereas before each row represented a single artwork, in the flattened table each row represents an individual tag belonging to one artwork.


To flatten these nested tags, we can use json_normalize by specifying the element to unnest in the record_path. We also include the objectID in the meta parameter so we don’t lose the relationship between a tag and its original artwork. Later on, we can join this tags table back to our main DataFrame if we want.


content_copy Copy

tags_df = pd.json_normalize(
    all_objects_data,
    record_path='tags',
    meta=['objectID']
)


5. Visualizing the most frequent themes


The MET API provides a tags field containing descriptive terms associated with each artwork. To understand the prevailing themes in Goya’s works — famous for documenting the social upheaval and dark realities of his era — we can extract these terms and calculate their frequency.


Once we isolate the individual tags into a new column, we can use matplotlib to create a horizontal bar plot of the top 10 terms and check if indeed his artwork contained themes related to death and misery.


content_copy Copy

import matplotlib.pyplot as plt

# Calculate the frequency of each term for the filtered Goya artworks
# We filter tags_df to only include IDs present in our filtered goya_df
term_frequency = tags_df[tags_df['objectID'].isin(goya_df['objectID'])]['term'].value_counts().reset_index()
term_frequency.columns = ['term', 'count']

# Select the top N terms for better readability if there are many unique terms
# For this example, let's take the top 10 terms
top_terms = term_frequency.head(10).sort_values(by='count', ascending=True)

plt.figure(figsize=(12, 8))
plt.barh(top_terms['term'], top_terms['count'], color='#FF6885')

plt.title('Top 10 Most Frequent Terms in Goya Dataset', fontsize=20)
plt.xlabel('Frequency', fontsize=16)
plt.ylabel('Term', fontsize=16)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.tight_layout()
plt.show()


Top 10 Most Frequent Terms in Goya Dataset

Top 10 Most Frequent Terms chart


The resulting visualization provides a fascinating window into Goya’s thematic world. Beyond common subjects like “Men,” “Women,” and “Portraits,” we see a strong representation of “Bulls” (reflecting his famous Tauromaquia series) and “Self-portraits.”


Most strikingly, terms like “Death” and “Suffering” appear prominently in the top 10. This data-driven insight confirms Goya’s historical reputation as an artist who didn’t shy away from the darker aspects of the human experience. By quantifying these themes through the MET API, we move from subjective observation to empirical evidence of his artistic focus.


The sleep of reason produces monsters

Plate 43 from "Los Caprichos": The sleep of reason produces monsters (El sueño de la razon produce monstruos)


You could also use the main dataset we created to collect a series of images of Goya works. I am thinking of using AI to help me download all images of Goya in the public domain and try to build a model to describe or classify them in Python. Feel free to use the data and let me know about your analysis. Leave your comments or any questions below and happy coding!


Conclusions




April 16, 2026 12:00 AM UTC

April 15, 2026


Django Weblog

Django Has Adopted Contributor Covenant 3

We’re excited to announce that Django has officially adopted Contributor Covenant 3 as our new Code of Conduct! This milestone represents the completion of a careful, community-driven process that began earlier this year.

What We’ve Accomplished

Back in February, we announced our plan to adopt Contributor Covenant 3 through a transparent, multi-step process. Today, we’re proud to share that we’ve completed all three steps:

Step 1 (Completed February 2026): Established a community-driven process for proposing and reviewing changes to our Code of Conduct.

Step 2 (Completed March 2026): Updated our Enforcement Manual, Reporting Guidelines, and FAQs to align with Contributor Covenant 3 and incorporate lessons learned from our working group’s experience.

Step 3 (Completed April 2026): Adopted the Contributor Covenant 3 with Django-specific enhancements.

Why Contributor Covenant 3?

Contributor Covenant 3 represents a significant evolution in community standards, incorporating years of experience from communities around the world. The new version:

By adopting this widely-used standard, Django joins a global community of projects committed to fostering welcoming, inclusive spaces for everyone.

What’s New in Django’s Code of Conduct

While we’ve adopted Contributor Covenant 3 as our foundation, we’ve also made Django-specific enhancements:

You can view the complete changelog of changes at our Code of Conduct repository.

Community-Driven Process

This adoption represents months of collaborative work. The Code of Conduct Working Group reviewed community feedback, consulted with the DSF Board, and incorporated insights from our enforcement experience. Each step was completed through pull requests that were open for community review and discussion.

We’re grateful to everyone who participated in this process—whether by opening issues, commenting on pull requests, joining forum discussions, or simply taking the time to review and understand the changes.

Where to Find Everything

All of our Code of Conduct documentation is available on both djangoproject.com and our GitHub repository:

How You Can Continue to Help

The Code of Conduct is a living document that will continue to evolve with our community’s needs:

Thank You

Creating a truly welcoming and inclusive community is ongoing work that requires participation from all of us. Thank you for being part of Django’s community and for your commitment to making it a safe, respectful space where everyone can contribute and thrive.

If you have questions about the new Code of Conduct or our processes, please don’t hesitate to reach out to the Code of Conduct Working Group at conduct@djangoproject.com.


Posted by Dan Ryan on behalf of the Django Code of Conduct Working Group

April 15, 2026 08:49 PM UTC


Real Python

Variables in Python: Usage and Best Practices

In Python, variables are symbolic names that refer to objects or values stored in your computer’s memory. They allow you to assign descriptive names to data, making it easier to manipulate and reuse values throughout your code. You create a Python variable by assigning a value using the syntax variable_name = value.

By the end of this tutorial, you’ll understand that:

  • Variables in Python are symbolic names pointing to objects or values in memory.
  • You define variables by assigning them a value using the assignment operator.
  • Python variables are dynamically typed, allowing type changes through reassignment.
  • Python variable names can include letters, digits, and underscores but can’t start with a digit. You should use snake case for multi-word names to improve readability.
  • Variables exist in different scopes (global, local, non-local, or built-in), which affects how you can access them.
  • You can have an unlimited number of variables in Python, limited only by computer memory.

To get the most out of this tutorial, you should be familiar with Python’s basic data types and have a general understanding of programming concepts like loops and functions.

Don’t worry if you don’t have all this knowledge yet and you’re just getting started. You won’t need this knowledge to benefit from working through the early sections of this tutorial.

Get Your Code: Click here to download the free sample code that shows you how to use variables in Python.

Take the Quiz: Test your knowledge with our interactive “Variables in Python: Usage and Best Practices” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Variables in Python: Usage and Best Practices

Test your understanding of Python variables, from creation and naming conventions to dynamic typing, scopes, and type hints.

Getting to Know Variables in Python

In Python, variables are names associated with concrete objects or values stored in your computer’s memory. By associating a variable with a value, you can refer to the value using a descriptive name and reuse it as many times as needed in your code.

Variables behave as if they were the value they refer to. To use variables in your code, you first need to learn how to create them, which is pretty straightforward in Python.

Creating Variables With Assignments

The primary way to create a variable in Python is to assign it a value using the assignment operator and the following syntax:

Python Syntax
variable_name = value

In this syntax, you have the variable’s name on the left, then the assignment (=) operator, followed by the value you want to assign to the variable at hand. The value in this construct can be any Python object, including strings, numbers, lists, dictionaries, or even custom objects.

Note: To learn more about assignments, check out Python’s Assignment Operator: Write Robust Assignments.

Here are a few examples of variables:

Python
>>> word = "Python"

>>> number = 42

>>> coefficient = 2.87

>>> fruits = ["apple", "mango", "grape"]

>>> ordinals = {1: "first", 2: "second", 3: "third"}

>>> class SomeCustomClass: pass
>>> instance = SomeCustomClass()

In this code, you’ve defined several variables by assigning values to names. The first five examples include variables that refer to different built-in types. The last example shows that variables can also refer to custom objects like an instance of your SomeCustomClass class.

Setting and Changing a Variable’s Data Type

Apart from a variable’s value, it’s also important to consider the data type of the value. When you think about a variable’s type, you’re considering whether the variable refers to a string, integer, floating-point number, list, tuple, dictionary, custom object, or another data type.

Python is a dynamically typed language, which means that variable types are determined and checked at runtime rather than during compilation. Because of this, you don’t need to specify a variable’s type when you’re creating the variable. Python will infer a variable’s type from the assigned object.

Note: In Python, variables themselves don’t have data types. Instead, the objects that variables reference have types.

For example, consider the following variables:

Python
>>> name = "Jane Doe"
>>> age = 19
>>> subjects = ["Math", "English", "Physics", "Chemistry"]

>>> type(name)
<class 'str'>
>>> type(age)
<class 'int'>
>>> type(subjects)
<class 'list'>

In this example, name refers to the "Jane Doe" value, so the type of name is str. Similarly, age refers to the integer number 19, so its type is int. Finally, subjects refers to a list, so its type is list. Note that you don’t have to explicitly tell Python which type each variable is. Python determines and sets the type by checking the type of the assigned value.

Read the full article at https://realpython.com/python-variables/ »


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

April 15, 2026 02:00 PM UTC


PyCon

Introducing the 7 Companies on Startup Row at PyCon US 2026

Each year at PyCon US, Startup Row highlights a select group of early-stage companies building ambitious products with Python at their core. The 2026 cohort reflects a rapidly evolving landscape, where advances in AI, data infrastructure, and developer tooling are reshaping how software is built, deployed, and secured.

This year’s companies aim to solve an evolving set of problems facing independent developers and large-scale organizations alike: securing AI-driven applications, managing multimodal data, orchestrating autonomous agents, automating complex workflows, and extracting insight from increasingly unstructured information. Across these domains, Python continues to serve as a unifying layer: encouraging experimentation, enabling systems built to scale, and connecting open-source innovation with real-world impact.

Startup Row brings these emerging teams into direct conversation with the Python community at PyCon US. Throughout the conference, attendees can meet founders, explore new tools, and see firsthand how these companies are applying Python to solve meaningful problems. For the startups in attendance, it’s an opportunity to share their work, connect with users and collaborators, and contribute back to the ecosystem that helped shape them. Register now to experience Startup Row and much more at PyCon US 2026.

Supporting Startups at PyCon US

There are many ways to support Startup Row companies, during PyCon US and long after the conference wraps:
  • Stop by Startup Row: Spend a few minutes with each team, ask what they’re building, and see their products in action. 
  • Try their tools: Whether it’s an open-source library or a hosted service, hands-on usage (alongside constructive feedback) is one of the most valuable forms of support. If a startup seems compelling, consider a pilot project and become a design partner.
  • Share feedback: Early-stage teams benefit enormously from thoughtful questions, real-world use cases, and honest perspectives from the community.
  • Contribute to their open source projects: Many Startup Row companies are deeply rooted in open source. Startup Row companies with open-source roots welcome bug reports, documentation improvements, and pull requests. Contributions and constructive feedback are always appreciated.
  • Help spread the word: If you find something interesting, tell a friend, post about it, or share it with your team. (And if you're posting to social media, consider using tags like #PyConUS and #StartupRow to share the love.)
  • Explore opportunities to work together: Many of these companies are hiring, looking for design partners, or open to collaborations; don’t hesitate to ask.
  • But, most importantly, be supportive. Building a startup is hard, and every team is learning in real time. Curiosity, patience, and encouragement make a meaningful difference. 
Without further ado, let's...

Meet Startup Row at PyCon US 2026

We’re excited to introduce the companies selected for Startup Row at PyCon US 2026.

Arcjet

Embedding security directly into application code is fast becoming as indispensable as logging, especially as AI services open new attack surfaces. Arcjet offers a developer‑first platform that lets teams add bot detection, rate limiting and data‑privacy checks right where the request is processed.

The service ships open‑source JavaScript and Python SDKs that run a WebAssembly module locally before calling Arcjet’s low‑latency decision API, ensuring full application context informs every security verdict. Both SDKs are released under a permissive open‑source license, letting developers integrate the primitives without vendor lock‑in while scaling usage through Arcjet’s SaaS tiered pricing.

The JavaScript SDK alone has earned ≈1.7 k GitHub stars and the combined libraries have attracted over 1,000 developers protecting more than 500 production applications. Arcjet offers a free tier and usage‑based paid plans, mirroring Cloudflare’s model to serve startups and enterprises alike.

Arcjet is rolling out additional security tools and deepening integrations with popular frameworks such as FastAPI and Flask, aiming to broaden adoption across AI‑enabled services. In short, Arcjet aims to be the security‑as‑code layer every modern app ships with.

CapiscIO

As multi‑agent AI systems become the backbone of emerging digital workflows, developers lack a reliable way to verify agent identities and enforce governance. CapiscIO steps into that gap, offering an open‑core trust layer built for the nascent agent economy.

CapiscIO offers cryptographic Trust Badges, policy enforcement, and tamper‑evident chain‑of‑custody wrapped in a Python SDK. Released under Apache 2.0, it ships a CLI, LangChain integration, and an MCP SDK that let agents prove identity without overhauling existing infrastructure.

The capiscio‑core repository on GitHub hosts the open‑source core and SDKs under Apache 2.0, drawing early contributors building agentic pipelines.

Beon de Nood, Founder & CEO, brings two decades of enterprise development experience and a prior successful startup to the table. “AI governance should be practical, not bureaucratic. Organizations need visibility into what they have, confidence in what they deploy, and control over how agents behave in production,” he says.

CapiscIO is continuously adding new extensions, expanding its LangChain and MCP SDKs, and preparing a managed agent‑identity registry for enterprises. In short, CapiscIO aims to be the passport office of the agent economy, handing each autonomous component an unspoofable ID and clear permissions.

Chonkie

The explosion of retrieval‑augmented generation (RAG) is unlocking AI’s ability to reason over ever‑larger knowledge bases. Yet the first step of splitting massive texts into meaningful pieces still lags behind.

Chonkie offers an open‑core suite centered on Memchunk, a Python library with Cython acceleration that delivers up to 160 GB/s throughput and ten chunking strategies under a permissive license. It also ships Catsu, a unified embeddings client for nine providers, and a lightweight ingestion layer; the commercial Chonkie Labs service combines them into a SaaS that monitors the web and synthesises insights.

Co‑founder and CEO Shreyash  Nigam, who grew up in India and met his business partner in eighth grade, reflects the team’s open‑source ethos, saying “It’s fun to put a project on GitHub and see a community of developers crowd around it.” That enthusiasm underpins Chonkie’s decision to release its core tooling openly while building a commercial deep‑research service.

Backed by Y  Combinator’s Summer  2025 batch, Chonkie plans to grow from four to six engineers and launch the next version of Chonkie Labs later this year, adding real‑time web crawling and multi‑modal summarization. In short, Chonkie aims to be the Google of corporate intelligence.

Pixeltable

Multimodal generative AI is turning simple datasets into sprawling collections of video, images, audio and text, forcing engineers to stitch together ad‑hoc pipelines just to keep data flowing. That complexity has created a new bottleneck for teams trying to move from prototype to production.

The open‑source Python library from Pixeltable offers a declarative table API that lets developers store, query and version multimodal assets side by side while embedding custom Python functions. Built with incremental update capabilities, combined lineage and schema tracking, and a development‑to‑production mirror, the platform also provides orchestration capabilities that keep pipelines reproducible without rewriting code.

The project has earned ≈1.6 k  GitHub stars and a growing contributor base, closed a $5.5  million seed round in December 2024, and is already used by early adopters such as Obvio and Variata to streamline computer‑vision workflows.

Co‑founder and CTO Marcel  Kornacker, who previously founded Apache Impala and co-founded Apache Parquet, says “Just as relational databases revolutionized web development, Pixeltable is transforming AI application development.”

The company's roadmap centers on launching Pixeltable Cloud, a serverless managed service that will extend the open core with collaborative editing, auto‑scaling storage and built‑in monitoring. In short, Pixeltable aims to be the relational database of multimodal AI data.

SubImage

The sheer complexity of modern multi‑cloud environments turns security visibility into a labyrinth, and  SubImage offers a graph‑first view that cuts through the noise.

It builds an infrastructure graph using the open‑source Cartography library (Apache‑2.0, Python), then highlights exploit chains as attack paths and applies AI models to prioritize findings based on ownership and contextual risk.

Cartography, originally developed at Lyft and now a Cloud Native Computing Sandbox project, has ≈3.7 k GitHub stars, is used by over 70 organizations, and SubImage’s managed service already protects security teams at Veriff and Neo4j; the company closed a $4.2  million seed round in November 2025.

Co‑founder Alex  Chantavy, an offensive‑security engineer, says “The most important tool was our internal cloud knowledge graph because it showed us a map of the easiest attack paths … One of the most effective ways to defend an environment is to see it the same way an attacker would.”

The startup is focusing on scaling its managed service and deepening AI integration as it targets larger enterprise customers. In short, SubImage aims to be the map of the cloud for defenders.

Tetrix

Private‑market data pipelines still rely on manual downloads and spreadsheet gymnastics, leaving analysts chasing yesterday’s numbers. Tetrix’s AI investment intelligence platform is part of a wave that brings automation to this lagging workflow.

Built primarily in Python, Tetrix automates document collection from fund portals and other sources, extracts structured data from PDFs and other unstructured sources using tool-using language models, then presents exposures, cash flows, and benchmarks through an interactive dashboard that also accepts natural‑language queries.

The company is growing quickly, doubling revenue quarter over quarter and, at least so far, maintains an impressive record of zero customer churn. In the coming year or so, Tetrix plans to triple its headcount from fifteen to forty‑five employees.

TimeCopilot

Time‑series forecasting has long been a tangled mix of scripts, dashboards, and domain expertise, and the recent surge in autonomous agents is finally giving it a unified voice. Enter TimeCopilot, an open‑source framework that brings agentic reasoning to the heart of forecasting.

The platform, built in Python under a permissive open‑source license, lets users request forecasts in plain English. It automatically orchestrates more than thirty models from seven families, including Chronos and TimesFM, while weaving large language model reasoning into each prediction. Its declarative API was born from co‑founder  Azul Garza‑Ramírez’s economics background and her earlier work on TimeGPT for Nixtla (featured SR'23), evolving from a weekend experiment started nearly seven years ago.

The TimeCopilot/timecopilot repository has amassed roughly 420  stars on GitHub, with the release of OpenClaw marking a notable spike in community interest.

Upcoming plans include a managed SaaS offering with enterprise‑grade scaling and support, the rollout of a benchmarking suite to measure agentic forecast quality, and targeted use cases such as predicting cloud‑compute expenses for AI workloads.

Thank You's and Acknowledgements

Startup Row is a volunteer-driven program, co-led by Jason D. Rowley and Shea Tate-Di Donna (SR'15; Zana, acquired Startups.com), in collaboration with the PyCon US organizing team. Thanks to everyone who makes PyCon US possible.

We also extend a gracious thank-you to all startup founders who submitted applications to Startup Row at PyCon US this year. Thanks again for taking the time to share what you're building. We hope to help out in whatever way we can.

Good luck to everyone, and see you in Long Beach, CA!

April 15, 2026 01:03 PM UTC


Real Python

Quiz: Design and Guidance: Object-Oriented Programming in Python

Test your understanding of the Design and Guidance: Object-Oriented Programming in Python video course.

You’ll revisit single responsibility, open-closed, Liskov substitution, interface segregation, and dependency inversion. You’ll also review when to use classes in Python and alternatives to inheritance like composition and dependency injection.


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

April 15, 2026 12:00 PM UTC

April 14, 2026


PyCoder’s Weekly

Issue #730: Typing Django, Dictionaries, pandas vs Polars, and More (April 14, 2026)

#730 – APRIL 14, 2026
View in Browser »

The PyCoder’s Weekly Logo


Typing Your Django Project in 2026

Django was first released 10 years before Python standardized its type hints syntax. Because of this it’s not surprising that getting type hints to work in your Django project is not trivial.
ANŽE'S BLOG

Dictionaries in Python

Learn how dictionaries in Python work: create and modify key-value pairs using dict literals, the dict() constructor, built-in methods, and operators.
REAL PYTHON

Secure Your Python MCP Servers With Auth and Access Control

alt

Use the Descope Python MCP SDK to easily secure your MCP server with user auth, consent, OAuth 2.1 with PKCE, MCP client registration, scope-based access at the tool level, and more →
DESCOPE sponsor

pandas vs Polars: Backed by a 10 Million Row Study

A benchmark study of 10M rows comparing Pandas vs. Polars. Explore the architectural shifts, lazy execution, and Rust-based speed of modern data tools.
QUBRICA.COM • Shared by Rakshath

Python 3.15.0a8, 3.14.4 and 3.13.13 Released

PYTHON.ORG

PyCon US 2026 Schedule Is Live

PYCON US

Django Security Releases: 6.0.4, 5.2.13, and 4.2.30

DJANGO SOFTWARE FOUNDATION

DjangoCon Europe 2027 Call for Organizers

DJANGO SOFTWARE FOUNDATION

Articles & Tutorials

Switching All My Packages to PyPI Trusted Publishing

Matthias maintains several Python packages including the django-debug-toolbar. To help protect these projects from malicious release uploads, he’s switching to the PyPI Trusted Publishing mechanism. This article explains why and what it protects.
MATTHIAS KESTENHOLZ

Cutting Python Web App Memory Over 31%

Michael reduced Python web app memory by 3.2 GB using async workers, import isolation, the Raw+DC database pattern, and disk caching. The article includes detailed before and after numbers for each technique.
MICHAEL KENNEDY

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

Understanding FSMs by Building One From Scratch

After having worked with the transitions library for a while, Bob wondered how Finite State Machines work under the hood. This article shows you how he built one from scratch, modelling GitHub pull requests.
BOB BELDERBOS • Shared by Bob Belderbos

Python for Java Developers

The article outlines how Java developers can transition to Python by building on their existing object-oriented knowledge while focusing on the key differences between the two languages.
NIKOS VAGGALIS • Shared by Andrew Solomon

Why Aren’t We uv Yet?

Reading articles on the net you’d think that uv was all the things. It is popular but not as much as you’d think. This article looks at the data.
ALEX YANKOV

Using Loguru to Simplify Python Logging

Learn how to use Loguru for simpler Python logging, from zero-config setup and custom formats to file rotation, retention, and adding context.
REAL PYTHON course

Quiz: Using Loguru to Simplify Python Logging

REAL PYTHON

SQLite Features You Didn’t Know It Had

SQLite has evolved far beyond a simple embedded database. Explore modern features like JSON, FTS5, window functions, strict tables, and more.
SLICKER.ME

Using a ~/.pdbrc File to Customize the Python Debugger

You can customize the Python debugger (PDB) by creating custom aliases within a .pdbrc file in your home directory. Read on to learn how.
TREY HUNNER

Python: Introducing Profiling-Explorer

Adam has added another project to his list of profiling tools, this one is for examining data from Python’s built-in profilers.
ADAM JOHNSON

Projects & Code

dj-signals-panel: View Django Signals in the Admin

GITHUB.COM/YASSI

form-filler: Generate Bookmarklets That Fill Web Forms

GITHUB.COM/HAMATTI

great-docs: Documentation Site Generator for Python Packages

GITHUB.COM/POSIT-DEV • Shared by Richard Iannone

rsloop: An Event Loop for Asyncio Written in Rust

GITHUB.COM/RUSTEDBYTES • Shared by Yehor Smoliakov

S3 Commander: Python Based AWS S3 Browser

GITHUB.COM/ROMANZDK • Shared by Roman

Events

DjangoCon Europe 2026

April 15 to April 20, 2026
DJANGOCON.EU

Weekly Real Python Office Hours Q&A (Virtual)

April 15, 2026
REALPYTHON.COM

PyData Bristol Meetup

April 16, 2026
MEETUP.COM

PyLadies Dublin

April 16, 2026
PYLADIES.COM

PyTexas 2026

April 17 to April 20, 2026
PYTEXAS.ORG

Chattanooga Python User Group

April 17 to April 18, 2026
MEETUP.COM

PyCon Austria 2026

April 19 to April 21, 2026
PYCON.AT


Happy Pythoning!
This was PyCoder’s Weekly Issue #730.
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 ]

April 14, 2026 07:30 PM UTC


Real Python

Vector Databases and Embeddings With ChromaDB

The era of large language models (LLMs) is here, bringing with it rapidly evolving libraries like ChromaDB that help augment LLM applications. You’ve most likely heard of chatbots like OpenAI’s ChatGPT, and perhaps you’ve even experienced their remarkable ability to reason about natural language processing (NLP) problems.

Modern LLMs, while imperfect, can accurately solve a wide range of problems and provide correct answers to many questions. However, due to the limits of their training and the number of text tokens they can process, LLMs aren’t a silver bullet for all tasks.

You wouldn’t expect an LLM to deliver relevant responses about topics that don’t appear in its training data. For example, if you asked ChatGPT to summarize information in confidential company documents, you’d be out of luck. You could show some of these documents to ChatGPT, but there’s a limit to how many documents you can upload before you exceed ChatGPT’s maximum token count. How would you select which documents to show ChatGPT?

To address these limitations and scale your LLM applications, a great option is to use a vector database like ChromaDB. A vector database allows you to store encoded unstructured objects, like text, as lists of numbers that can be compared to one another. For instance, you can find a collection of documents relevant to a question you’d like an LLM to answer.

In this video course, you’ll learn about:

After watching, you’ll have the foundational knowledge to use ChromaDB in your NLP or LLM applications. Before watching, you should be comfortable with the basics of Python and high school math.


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

April 14, 2026 02:00 PM UTC

Quiz: Explore Your Dataset With pandas

In this quiz, you’ll test your understanding of Explore Your Dataset With pandas.

By working through this quiz, you’ll revisit pandas core data structures, reading CSV files, indexing and filtering data, grouping and aggregating results, understanding dtypes, and combining DataFrames.

This quiz helps you apply the core techniques from the course so you can turn a large dataset into clear, reproducible insights.


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

April 14, 2026 12:00 PM UTC

Quiz: Altair: Declarative Charts With Python

In this quiz, you’ll test your understanding of Altair: Declarative Charts With Python.

By working through this quiz, you’ll revisit Altair’s core grammar of Data, Mark, and Encode, encoding channels and type shorthands, interactive selections with brushing and linked views, and common limitations to watch out for.


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

April 14, 2026 12:00 PM UTC

Quiz: Vector Databases and Embeddings 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 ]

April 14, 2026 12:00 PM UTC


Python Software Foundation

PyCon US 2026: Why we're asking you to think about your hotel reservation

The PyCon US 2026 team has already covered some of the fun, unexpected, and meaningful reasons you’ll want to stay in the PyCon US hotel block. The PSF wants to use our blog to give a different angle, to keep being transparent with you, and share a little bit of real talk on the economics of holding a conference in the US at this moment in time. The short version is, if you’re joining us in Long Beach, please book the official PyCon US hotels through your PyCon US 2026 dashboard, because bookings in our hotel block are critical to the economic viability of the event.

Context on hotel bookings & PyCon US

For many years, PyCon US has relied on hotel booking commissions to help pay for our conference space. This helps us keep the event tickets affordable and to continue offering Travel Grants to community members who might not otherwise be able to attend PyCon US. Once your event outgrows academic spaces, donated conference rooms, or theatre spaces, working with the hotels is the industry’s standard way to pay for a professional convention center space. You commit to a certain number of hotel nights blocked off at nearby hotels, based on your event’s numbers from previous years, and in return, you get a reduced rental charge at the convention center. If you sell enough rooms, you additionally earn a small percentage of the revenue from those rooms, i.e. a commission. If, on the other hand, you don’t sell enough rooms, you owe damages to the hotels–essentially paying the full rate for the rooms they reserved for your event but didn’t sell. 


This system has worked well for the PSF and PyCon US until this year. At the height of the pre-pandemic years, we brought in over $200,000 in hotel commissions. Even last year in Pittsburgh, we fully sold out one hotel and our total commission in 2025 was a healthy $95,909. Unfortunately, this year our hotel bookings are far behind the level they need to avoid damages, let alone earn any commission. We attribute this largely to the sad but understandable decline in willingness of international attendees, as well as some vulnerable domestic attendees, to travel to PyCon US, given the current environment. The bottom line is, if PyCon US hotel booking trends continue at their current pace, the PSF is on track to owe over $200,000 in damages under our hotel contracts.

We are not alone in this. The travel industry has been talking about the slump in foreign visitors to the US for months. The decline in foreign tourism revenue is also making the hotels less interested in being generous with our rates, contracts, and deadlines, since most hotels have seen declines in their bookings all year, not just during our event. Everyone is feeling the squeeze.

Where we’re at now

PyCon US ticket sales are only lagging by a bit. Local attendees buy their tickets later, which is something we anticipate, but this year’s hotel bookings are lagging by a lot compared to last year:

PyCon US Ticket sales as of April 10, 2025: 1,565

​​​​PyCon US Ticket sales as of April 12, 2026: 1,333


Hotel nights sold as of April 10th, 2025: 3,155 

Hotel nights sold as of April 12th, 2026: 2,192


Hotel nights we need to sell by April 20th, 2026 to avoid damages: 3,338

Additional Hotel nights needed by April 20th, 2026 to avoid damages: 1,146

The PSF signed a contract for the Long Beach venue back in July of 2023. At that time we couldn‘t have foreseen this current situation where interest in coming to the US has sharply declined due to increased risk. In response, we have focused on attracting more domestic attendees, and that has been going pretty well, but it hasn’t made up for the macroeconomic and geopolitical impacts on our attendance. 

How you can help

We’ll need as many of our attendees as possible to book the official conference hotel before the deadline: The first hotel block closes on April 20th, and the last block closes April 24th. 

Booking the official conference hotel helps us keep PyCon US running and affordable and it’s also a lot of fun to stay where the action is. If you are planning to join us at PyCon US this year (and we hope you can because there are a lot of great things happening at the event this year!) then we hope you will consider booking an official conference hotel

To book in our hotel block, first register for the conference, and then book your room directly from your attendee dashboard. If you need help or would like to reserve a group of rooms, please contact our housing partner Orchid: 1-877-505-0689 or help@orchid.events. Our hotels page has a full list of the four hotel options and their deadlines.

A final note

We want to thank you for your commitment to the community that makes PyCon US the special event it is. We hope to see you there to learn, collaborate, and share lots of fun moments. 

For all those who can’t be at PyCon US this year for whatever reason: you will be sorely missed and we hope to see you at a future edition of the event!

 

April 14, 2026 10:13 AM UTC


Seth Michael Larson

Add Animal Crossing events to your digital calendar

Animal Forest (“Dōbutsu no Mori” or “どうぶつの森”) was released in Japan for the Nintendo 64 on April 14th, 2001: exactly 25 years ago today! To celebrate this beloved franchise I have created calendars for each of the “first-generation” Animal Crossing games that you can load into calendar apps like Google Calendar or Apple Calendars to see events from your town.

These calendars include holidays, special events, igloo and summer campers, and more. Additionally, I've created a tool which can generate importable calendars for the birthdays of villagers in your town using data from future titles and star signs from e-Reader cards.

Select which game, region, and language you are interested in and then scan the QR code or copy the URL and import the calendar manually into your calendar application. Note that calendars are only available for a valid “game + region + language” combinations such as: “Animal Forest e+ + NTSC-J + Japanese”.


Continue reading on sethmlarson.dev ...



Thanks for keeping RSS alive! ♥

April 14, 2026 12:00 AM UTC

April 13, 2026


Python Software Foundation

Reflecting on Five Years as the PSF’s First CPython Developer in Residence

After nearly five wonderful years at the Python Software Foundation as the inaugural CPython Developer in Residence, it's time for me to move on. I feel honored and honestly so lucky to have had the opportunity to kick off the program that now includes several wonderful full-time engineers. I'm glad to see the program left in good hands. The vacancy created by my departure will be filled after PyCon US as the PSF is currently focused on delivering a strong event. I'm happy to share that Meta will continue to sponsor the CPython Developer in Residence role at least through mid-2027. The program is safe.

Łukasz with PSF's Security Developer in Residence Seth Larson and PyPI Safety & Security Engineer Mike Fielder at PyCon US 2025


As a member of the Python Steering Council during Łukasz’s tenure as Developer in Residence, I express my personal gratitude for his dedication to the CPython project and the larger Python community. I know I echo the sentiment of everyone who has served on the Council during his time as DiR. He has defined what it means to be a Developer in Residence - a position that is incredibly important to the smooth operation of the CPython project, in large and small ways, visible and hidden. Our bi-weekly meetings gave the Steering Council a detailed, unique, and invaluable contemporaneous perspective on what’s happening in CPython. Łukasz leaves big shoes to fill, and we wish him all the best in his next endeavor. It’s comforting to know that he will continue to be a Python leader and member of the core team.


-- Barry Warsaw; Python Steering Council member 2026


In my time as a developer in residence, I personally touched some pretty amazing projects like the transition to GitHub issues from bugs.python.org, the replacement of the mostly manual CLA process with an automated system, the introduction of free threading to Python, and the replacement of the interactive shell in the interpreter. And between the thousands of pull requests I've reviewed or authored, and the many less glamorous tasks like content moderation and keeping the lights on when it comes to core workflow, I've interacted with some amazing individuals. Some of them are core developers now. I've witnessed the full-time paid developer in residence roster at the Python Software Foundation grow from one person to five.


As for me, ever since seeing it for the first time in 2013, I had dreamed about moving permanently to Vancouver BC. This dream is coming true soon. As part of that move, I'm joining Meta as a software engineer on the Python Language Foundation team. In any case, I'm not disappearing from the open-source Python community. I'll be seeing you online and maybe even in person at Python-related conferences.


April 13, 2026 02:01 PM UTC


Real Python

How to Add Features to a Python Project With Codex CLI

After reading this guide, you’ll be able to use Codex CLI to add features to a Python project directly from your terminal. Codex CLI is an AI-powered coding assistant that runs inside your terminal. It understands your project structure, reads your files, and proposes multi-file changes using natural language instructions.

Instead of copying code from a browser or relying on an IDE plugin, you’ll use Codex CLI to implement a real feature in a multi-file Python project directly from your terminal:

Example of Using Codex CLI to Implement a Project Feature

In the following steps, you’ll install and configure Codex CLI, use it to implement a deletion feature in a contact book app, and then refine that feature through iterative prompting.

Take the Quiz: Test your knowledge with our interactive “How to Add Features to a Python Project With Codex CLI” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

How to Add Features to a Python Project With Codex CLI

Test your knowledge of Codex CLI, the AI-powered terminal tool for adding features to Python projects with natural language.

Prerequisites

To follow this guide, you should be familiar with the Python language. You’ll also need an OpenAI account with either a paid ChatGPT subscription or a valid API key, which you’ll connect to Codex CLI once you install it. Additionally, you’ll need to have Node.js installed, since Codex CLI is distributed as an npm package.

To make it easier for you to experiment with Codex CLI, download the RP Contacts project by clicking the link below:

The project RP Contacts is a text-based interface (TUI) that allows you to manage contacts directly in the terminal through a Textual app. It’s an adapted version of the project from Real Python’s tutorial Build a Contact Book App With Python, Textual, and SQLite. It differs from the original in that it uses uv to manage the project, and the TUI buttons Delete and Clear All haven’t been implemented—that’s what you’ll use Codex CLI for.

Once you’ve downloaded the project, you want to check that you can run it. As mentioned, the project uses uv for dependency management—you can tell by the uv.lock file in the project root—so make sure you have uv installed. If you don’t have uv yet, follow the official installation instructions.

Once you have uv installed and you’re at the root directory of the project, you can run the project:

Shell
$ uv run rpcontacts

When you run the command rpcontacts through uv for the first time, uv will create a virtual environment, install the dependencies of your project, and start the RP Contacts TUI. If all goes well, you should see a TUI in your terminal with a couple of buttons and an empty contact listing:

Contact Book Planned Main TUI

Once the TUI opens, create some test contacts by using the Add button and filling in the form that pops up. After creating a couple of fake contacts, quit the application by pressing Q.

Finally, you’ll want to initialize a Git repository at the root of your project and commit all your files:

Shell
$ git init .
$ git add .
$ git commit -m "First commit."

Codex CLI will modify your code, and you can never tell whether the changes will be good or not. Versioning your code makes it straightforward to roll back any changes made by LLMs if you don’t like them.

If you want to explore other AI-powered coding tools alongside Codex CLI, Real Python’s Python Coding With AI learning path brings together tutorials and video courses on AI-assisted coding, prompt engineering, and LLM development.

Step 1: Install and Configure Codex CLI

With all the accessory setup out of the way, it’s now time to install Codex CLI. For that, you’ll want to check the official OpenAI documentation to see the most up-to-date installation instructions. As of now, OpenAI recommends using npm:

Read the full article at https://realpython.com/codex-cli/ »


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

April 13, 2026 02:00 PM UTC


PyCon

How to Build Your PyCon US 2026 Schedule

Six Pathways Through the Talks

Finding your way through three days of world-class Python content

PyCon US 2026 runs May 13–19 in Long Beach, California, and with over 100 talks across five rooms over three days, the schedule can feel like a lot to navigate. The good news: whether you came to go deep on Python performance, level up your security knowledge, get practical Python insights for agentic AI, or finally understand what all the async fuss is about, there's a clear path through the content that's built for you. Register now to get in on the full experience. 

We mapped six attendee pathways through the full talks schedule with a bonus tutorial to pair with it, each one a curated sequence of sessions that focuses on a core Python topic. Think of them less as tracks and more as through-lines. Pick the one that matches where you are and what you want to walk away with to integrate into your work.

Python Performance: From Memory to Metal

If you want to understand why your Python is slow and what to actually do about it, this is your path. It runs across all three days and takes you from memory profiling fundamentals all the way to CPython internals with one of the core developers who is actually changing the way the runtime works.

Friday 

Saturday

Sunday

Pair it with a tutorial: Start the week with Arthur Pastel and Adrien Cacciaguerra's Wednesday tutorial Python Performance Lab: Sharpening Your Instincts. It's a hands-on lab designed to build the kind of performance intuition that makes everything in this pathway land harder.

Debugging and Observability: Finding What's Wrong and Why

This pathway is for engineers who spend too much time in production fires and want better tools for preventing and diagnosing them. It moves from memory leak storytelling through the brand new profiling and debugging interfaces, landing in Python 3.14 and 3.15.

Friday

Saturday

Pair it with a tutorial: Catherine Nelson and Robert Masson's Thursday tutorial Going from Notebooks to Production Code is a natural warm-up, it covers the gap between exploratory code and production systems, which is exactly where most debugging pain lives.

Concurrency and Async: Making Python Do More at Once

The concurrency story in Python is changing faster than it has in years. This pathway traces the thread from hardware-level parallelism through the GIL removal to practical async patterns for the systems people are actually building in 2026.

Friday 

Saturday

Pair it with a tutorial: Trey Hunner's Wednesday tutorial Lazy Looping in Practice: Building and Using Generators and Iterators is a perfect primer. Generators and iterators are the building blocks of Python's async model, and Hunner is one of the best teachers in the community at making these concepts click.

AI and Machine Learning: From Inference to Agents

The dedicated Future of AI with Python track runs all day Friday, May 15th, and it's one of the strongest single-day lineups in the schedule. This pathway threads the AI content across the full conference, from hardware fundamentals to production-grade inference.

Friday

Saturday

Pair it with a tutorial: Two tutorials are worth your attention here. Pamela Fox's Wednesday Build Your First MCP Server in Python is the fastest way to understand how agentic systems actually work under the hood — MCP is quickly becoming the standard way to give AI agents access to tools and data. And Isabel Michel's Wednesday Implementing RAG in Python: Build a Retrieval-Augmented Generation System gives you the hands-on foundation underneath most modern LLM applications.

Security: A Full Day Worth Taking Seriously

Saturday, May 16th, is the first-ever dedicated security track at PyCon US, and if security is anywhere near your professional concerns, you should plan to spend most of Saturday in Room 103ABC. Eleven experts. One room. A full day.

Saturday

Pair it with a tutorial: Paul Zuradzki's Wednesday tutorial, Practical Software Testing with Python is a strong complement: the discipline of writing tests and the discipline of writing secure code overlap more than most developers realize, and this tutorial gives you the testing foundation that makes security practices easier to implement and verify.

New to Python and Packaging: A First-Timer's Path Through the Conference

Not every pathway is about going deep. This one is for attendees who are newer to Python or who want to level up on tooling, packaging, and writing code that other people can actually use. It runs gently across all three days and ends with a satisfying arc.

Friday

Saturday

Sunday 

Pair it with a tutorial: Mason Egger's Thursday tutorial, Writing Pythonic Code: Features That Make Python Powerful, is the ideal warm-up for this entire pathway. It covers the idioms and language features that separate code that works from code that feels like Python, which is exactly the mindset the rest of this track builds on. Or if you are just getting started with no experience at all, try Python for Absolute Beginners.  If you've started and stopped learning to code before, or never got around to starting at all, sign up for this tutorial and start PyCon on a strong step.

However you come to PyCon US 2026, there's a path through the schedule built for you. The full talks schedule is at us.pycon.org/2026/schedule/talks, the full tutorials schedule is at https://us.pycon.org/2026/schedule/tutorials/, and registration is open now.

We'll see you in Long Beach.


PyCon US 2026 takes place May 13–19 in Long Beach, California. Talks run Friday, May 15th, through Sunday, May 17th.


April 13, 2026 12:21 PM UTC