skip to navigation
skip to content

Planet Python

Last update: September 11, 2025 09:43 PM UTC

September 11, 2025


Graham Dumpleton

Status of wrapt (September 2025)

The Python wrapt package recently turned 12 years old. Originally intended to be a module for monkey patching Python code, its wrapper object turned out to be a useful basis for creating Python decorators.

Back then, constructing decorators using function closures had various short comings and the resulting wrappers didn't preserve introspection and various other attributes associated with the wrapped function. Many of these issues have been resolved in updates to Python and the functools.wraps helper function, but wrapt based decorators were still useful for certain use cases such as being able to create a decorator where you could work out whether it was applied to a function, instance method, class method or even a class.

Downloads of wrapt

It is hard to tell how many people directly use wrapt, but helped by it being used internally in some widely used Python packages has actually resulted in wrapt making it into the list of PyPi top 100 packages by number of downloads. As I write this post it sits at position number 65, but it was at one point as high as about position 45. Either way, I am still surprised it makes it into that list at all, especially since the primary purpose of wrapt is to do something most view as dangerous, ie., monkey patch code.

Maintenance mode

As to the core problem that wrapt originally tried to solve, that was achieved many years ago and as such it has more or less been kept in maintenance mode ever since. Most changes over recent years have focused around ensuring it works with each new Python version and expanding on the set of Python wheels that are being released for different architectures. There are occassionaly bug fixes or tweaks but generally they relate to corner cases which have arisen due to people trying to do strange things when monkey patching code.

Version update

Even though few changes are being made, the plan is to soon release a new version. This version number for this release will jump from 1.17.X to 2.0.X.

The jump in major version isn't due to any known incompatibilities but more just to be safe since in this version all the old legacy code from Python 2 and early Python 3 versions has been removed.

PyCharm issues

The only obscure change which have any concern over relates to a specific corner case that should never occur in actual use, but does occur when using Python debugger IDEs such as PyCharm which offer live views of Python objects.

The problem in the case of PyCharm is that it can attempt to display the state of a Python object before the __init__() method has been called. Due to the wrapper object in wrapt being implemented in C code, that there is an accessor for the __wrapped__ attribute is visible, but until __init__() is called it has no value. All the same, PyCharm tries to access __wrapped__ during that time resulting in an exception.

For this exception when __wrapped__ is accessed in an uninitialised state a ValueError exception was being raised on the basis that the object was in an unknown state. The problem is that PyCharm doesn't gracefully handle this exception in this case and this somehow causes problems for PyCharm users.

What PyCharm prefers in this case is to see an AttributeError exception which results in it simply ignoring the attribute. Because it isn't known whether raising AttributeError instead of ValueError would cause issues for other existing code, I have been reticent to change the type of exception being raised.

At one point someone suggested raising a custom exception which inherits from both AttributeError and ValueError as a middle ground, allowing PyCharm to work but not cause issues for existing code.

Because one can't use multiple inheritence for custom exceptions implemented in C code, a fiddle has been required whereby the C extension code of wrapt reaches back to get a reference to an exception type implemented in Python code. Not elegant but appears to work so going to go with that and see if it works. Remember that this situation where the exception is raised should not even occur normally, so it may only be PyCharm that triggers it. Fingers crossed.

Typing hints

The other notable change for the next wrapt release will be the addition of support for type hints.

Adding type hints has been slow coming because wrapt supported Python 2 and older Python 3 versions well past when those versions became obsolete. Since such old versions were still supported, I didn't see it as practical to add support for type hints.

Even now, although the next wrapt version will still support Python version 3.8 and 3.9, the support for type hints will only be available if using Python 3.10 or later. This is because I finally realised that when using .pyi files to inject type hints, you could have version checks and only add them for selected versions. đŸ€Šâ€â™‚ïž

Another reason type hint support took so long to be added was simply because I wasn't that familiar with using them. Some users did propose changes to add type hints, but they seemed to me to be very minimal and not try and add support across the full APIs wrapt provided. Because I didn't understand type hints enough, I didn't want to risk adding them without really understanding how they worked.

This is not to say I am now an expert on type hints, I am definitely still a newbie and know just enough to be dangerous.

The resulting type hint support I added looks plenty scary to me and unfortunately still doesn't do everything I would like it to. My current belief is that due to the complicated overloading that wrapt does in certain APIs, that it just isn't possible within the limits of what the type hinting system can handle to do better than what I have managed. I haven't given up, but I also don't want to delay the next wrapt release any further, so will release it as is and revisit it later on to see if it can be made better.

Release candidates

With that all said, a release candidate for the next version of wrapt has been available for about a month. This can be installed by explicitly using wrapt==2.0.0rc2 or if your package installer supports it, to use unstable package versions such as release candidate versions.

After being out for a month I have not had any reports of the release candidate version causing any issues. That said, no one has said it works fine either. There has been something like 190 thousand downloads of the release candidate in that time though, so that is a good sign at least.

At this point it seems to be safe to release a 2.0.0 final version, so I will be aiming to double check everything over the coming week and get the new version released in time for Python 3.14. That said, Python 3.14 doesn't make it a priority as there was a 1.17.3 patch release version of wrapt a month ago which included Python wheels for Python 3.14, so every thing should be good to go for the new Python version.

List of changes

If you are interested in exactly what changes have made it into the next release, you can check out the develop branch for the wrapt docs on ReadTheDocs.

September 11, 2025 10:38 AM UTC

Back from the dead

I'm back.

Yes, it's been quite a long time. It's actually more than six years since my last blog post.

There are a few reasons for this. The main one is that after IBM acquired Red Hat, and later when I moved to VMware/Broadcom, I didn't always feel comfortable posting on my personal blog or speaking as freely as I would have liked. I was also less involved with my open source projects and busy working on something new that I couldn't actively promote at the time. So, I decided to step away from blogging for a while; I just didn't know how long that would end up being.

After being made redundant at Broadcom about a year ago, I've been on sabbatical, or what some call "micro retirement." Given the current state of the IT industry, this micro retirement may well turn into full retirement.

In my last three jobs, going back to 2010, I've worked remotely from home and only left the house for work when traveling to conferences or, on rare occasions, visiting the office. While I had the opportunity to travel for conferences during my time at New Relic and Red Hat, that changed when I moved to VMware. COVID disrupted everything, and travel was no longer possible. What I had expected to do at VMware also didn't really materialise, and I ended up working on other projects that didn't involve conference travel.

Although I never got to work on what I expected to at VMware, especially with COVID and all the uncertainty surrounding the Broadcom acquisition, by keeping my head down and staying out of sight, I was able to spend quite a lot of time working on a project of my own where I was able to set direction and do what I thought was required. An ideal situation for remote work and it suited me well, even if the overall work environment wasn't the best at the time.

Looking for a job now though, the prospect of being able to find a company who will take on a fully remote worker is very slim. All the companies I feel might have been a good place for me to work at are in the US, and these days even if they are hiring remote workers, you must still be in the US. Gone are the days where it was easier for someone located in Australia to get a job working for a US based company or team of people.

In the Australian job market, anything interesting is on site, or hybrid, requiring 2 or 3 days in the office, which isn't convenient for me. So right now I am a bit stuck on the job front and there is no clear path. The motivation for in office work just isn't there since I am so used to working from home.

Ideally I would find a company who actively supports open source and pays people to work on open source projects. Although I know of a few companies like this, as already noted the problem is they are in the US and will only hire remote workers who are also in the US.

So what next?

For now at least, the aim is to try and build links again with the Python community, since I have lost touch with what has been going on, not attending conferences like I used to, and not actively blogging.

I've only been doing the minimum required on my mod_wsgi and wrapt open source projects, and although I managed a flurry of activity on both a few weeks back, I held back from actually making a new release for each.

First priority, therefore, is to put out some blog posts on the current state of mod_wsgi and wrapt and get some new releases out, hopefully in time for Python 3.14.

I want to then start posting about my other new project called Educates. Although it will be new to others, the project is actually over 5 years old and has been available for quite a while, it just wasn't being promoted. The project may satisfy a small niche of users, but the amount of work I have put into it is significant, more than mod_wsgi or wrapt, so I don't want to cast it aside just yet.

So now that I have resurrected my blog site, hopefully I can keep the momentum up and meaningfully start applying myself to my open source projects and contribute to the Python community in some way, rather than spending an obsessive amount of time watching anime.

September 11, 2025 12:00 AM UTC

September 10, 2025


Real Python

How to Drop Null Values in pandas

Missing values can derail your analysis. In pandas, you can use the .dropna() method to remove rows or columns containing null values—in other words, missing data—so you can work with clean DataFrames. In this tutorial, you’ll learn how this method’s parameters let you control exactly which data gets removed. As you’ll see, these parameters give you fine-grained control over how much of your data to clean.

Dealing with null values is essential for keeping datasets clean and avoiding the issues they can cause. Missing entries can lead to misinterpreted column data types, inaccurate conclusions, and errors in calculations. Simply put, nulls can cause havoc if they find their way into your calculations.

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

  • You can use .dropna() to remove rows and columns from a pandas DataFrame.
  • You can remove rows and columns based on the content of a subset of your DataFrame.
  • You can remove rows and columns based on the volume of null values within your DataFrame.

To get the most out of this tutorial, it’s recommended that you already have a basic understanding of how to create pandas DataFrames from files.

You’ll use the Python REPL along with a file named sales_data_with_missing_values.csv, which contains several null values you’ll deal with during the exercises. Before you start, extract this file from the downloadable materials by clicking the link at the end of this section.

The sales_data_with_missing_values.csv file is based on the publicly available and complete sales data file from Kaggle. Understanding the file’s content isn’t essential for this tutorial, but you can explore the Kaggle link above for more details if you’d like.

You’ll also need to install both the pandas and PyArrow libraries to make sure all code examples work in your environment:

Windows PowerShell
PS> python -m pip install pandas pyarrow
Shell
$ python -m pip install pandas pyarrow

It’s time to refine your pandas skills by learning how to handle missing data in a variety of ways.

You’ll find all code examples and the sales_data_with_missing_values.csv file in the materials for this tutorial, which you can download by clicking the link below:

Get Your Code: Click here to download the free sample code that you’ll use to learn how to drop null values in pandas.

Take the Quiz: Test your knowledge with our interactive “How to Drop Null Values in pandas” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

How to Drop Null Values in pandas

Quiz yourself on pandas .dropna(): remove nulls, clean missing data, and prepare DataFrames for accurate analysis.

How to Drop Rows Containing Null Values in pandas

Before you start dropping rows, it’s helpful to know what options .dropna() gives you. This method supports six parameters that let you control exactly what’s removed:

  • axis: Specifies whether to remove rows or columns containing null values.
  • thresh and how: Define how many missing values to remove or retain.
  • subset: Limits the removal of null values to specific parts of your DataFrame.
  • inplace: Determines whether the operation modifies the original DataFrame or returns a new copy.
  • ignore_index: Resets the DataFrame index after removing rows.

Don’t worry if any of these parameters don’t make sense to you just yet—you’ll learn why each is used during this tutorial. You’ll also get the chance to practice your skills.

Note: Although this tutorial teaches you how pandas DataFrames use .dropna(), DataFrames aren’t the only pandas objects that use it.

Series objects also have their own .dropna() method. However, the Series version contains only four parameters—axis, inplace, how, and ignore_index—instead of the six supported by the DataFrame version. Of these, only inplace and ignore_index are used, and they work the same way as in the DataFrame method. The rest are kept for compatibility with DataFrame, but have no effect.

Indexes also have a .dropna() method for removing missing index values, and it contains just one parameter: how.

Before using .dropna() to drop rows, you should first find out whether your data contains any null values:

Python
>>> import pandas as pd

>>> pd.set_option("display.max_columns", None)

>>> sales_data = pd.read_csv(
...     "sales_data_with_missing_values.csv",
...     parse_dates=["order_date"],
...     date_format="%d/%m/%Y",
... ).convert_dtypes(dtype_backend="pyarrow")

>>> sales_data
    order_number           order_date       customer_name  \
0           <NA>  2025-02-09 00:00:00      Skipton Fealty
1          70041                 <NA>  Carmine Priestnall
2          70042  2025-02-09 00:00:00                <NA>
3          70043  2025-02-10 00:00:00     Lanni D'Ambrogi
4          70044  2025-02-10 00:00:00         Tann Angear
5          70045  2025-02-10 00:00:00      Skipton Fealty
6          70046  2025-02-11 00:00:00             Far Pow
7          70047  2025-02-11 00:00:00          Hill Group
8          70048  2025-02-11 00:00:00         Devlin Nock
9           <NA>                 <NA>                <NA>
10         70049  2025-02-12 00:00:00           Swift Inc

                product_purchased discount  sale_price
0    Chili Extra Virgin Olive Oil     True       135.0
1                            <NA>     <NA>       150.0
2       Rosemary Olive Oil Candle    False        78.0
3                            <NA>     True        19.5
4    Vanilla and Olive Oil Candle     <NA>       13.98
5    Basil Extra Virgin Olive Oil     True        <NA>
6    Chili Extra Virgin Olive Oil    False       150.0
7    Chili Extra Virgin Olive Oil     True       135.0
8   Lavender and Olive Oil Lotion    False       39.96
9                            <NA>     <NA>        <NA>
10  Garlic Extra Virgin Olive Oil     True       936.0

To make sure all columns appear on your screen, you configure pd.set_option("display.max_columns", None). By passing None as the second parameter, you make sure all columns are displayed.

You read the sales_data_with_missing_values.csv file into a DataFrame using the pandas read_csv() function, then view the data. The order dates are in the "%d/%m/%Y" format in the file, so to make sure the order_date data is read correctly, you use both the parse_dates and date_format parameters. The output reveals there are ten rows and six columns of data in your file.

Read the full article at https://realpython.com/how-to-drop-null-values-in-pandas/ »


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

September 10, 2025 02:00 PM UTC

Quiz: How to Drop Null Values in pandas

Challenge yourself with this quiz and see how much you understand about dropping null values in pandas.

Working through this quiz is a great way to revisit what you learned in the How to Drop Null Values in pandas tutorial. You’ll find most of the answers in the tutorial content, but for some of the questions, you might need to do some extra digging.


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

September 10, 2025 12:00 PM UTC


Quansight Labs Blog

Scaling asyncio on Free-Threaded Python

A recap on the work done in Python 3.14 to enable asyncio to scale on the free-threaded build of CPython.

September 10, 2025 12:00 AM UTC

September 09, 2025


PyCoder’s Weekly

Issue #698: Capturing Stdout, REPL Color, Feature History, and More (Sept. 9, 2025)

#698 – SEPTEMBER 9, 2025
View in Browser »

The PyCoder’s Weekly Logo


Python: Capture Stdout and Stderr in Unittest

When testing code that outputs to the terminal through either standard out (stdout) or standard error (stderr), you might want to capture that output and make assertions on it.
ADAM JOHNSO

Customizing Your Python 3.14 REPL’s Color Scheme

The upcoming release of Python 3.14 includes syntax highlighting in the REPL and you can control its color scheme and make it your own.
TREY HUNNER

On Demand: Design Long-Running, Human-Aware MCP

alt

Move beyond chatbots to build durable MCP servers that run for days, survive failures, and orchestrate elicitations and LLM sampling. Learn remote MCP trade-offs and patterns for sophisticated, or ambient, agents in this on-demand webinar →
TEMPORAL sponsor

A History of Python Versions and Features

Explore Python’s evolution from the 1990s to today with a brief history and demos of key features added throughout its lifetime.
REAL PYTHON course

PEP 794: Import Name Metadata (Accepted)

PYTHON.ORG

Python Type System and Tooling Survey 2025

GOOGLE.COM

Django Security Releases Issued: 5.2.6, 5.1.12, and 4.2.24

DJANGO SOFTWARE FOUNDATION

Articles & Tutorials

Large Language Models on the Edge of the Scaling Laws

What’s happening with the latest releases of large language models? Is the industry hitting the edge of the scaling laws, and do the current benchmarks provide reliable performance assessments? This week on the show, Jodie Burchell returns to discuss the current state of LLM releases.
REAL PYTHON podcast

Python Has Had Async for 10 Years

Anthony Shaw poses the question: Python has had async for 10 years, so why isn’t it more popular? He dives deep on where async is useful and where it is limited. Associated HN discussion.
ANTHONY SHAW

Engineer-led Demos, Live AMA, and More – all at Glean:LIVE

alt

Don’t miss Glean’s product launch on Sept 25th. Get a first look at Glean’s new Assistant, see how to vibe code an agent, and catch engineer-led demos. This launch is all about empowering you with a more personalized experience and upleveling the skills only you can bring to your work. Register now! here →
GLEAN sponsor

Top 6 Python Libraries for Visualization: Which One to Use?

The vast number of Python visualization libraries can be overwhelming. This article shows you the pros and cons of some the popular libraries, including Matplotlib, seaborn, Plotly, Bokeh, Altair, and Pygal.
CODECUT.AI ‱ Shared by Khuyen Tran

Open Source Is a Gift

This opinion piece talks about how open source isn’t just a gift of free libraries, but the gift of learning from others who are developing in public.
JOSH THOMAS.

Managing Multiple Python Versions With pyenv

Learn how to use pyenv to manage multiple Python versions, prevent conflicts, and keep your projects compatible and development smooth.
REAL PYTHON

Quiz: Managing Multiple Python Versions With pyenv

REAL PYTHON

uv vs pip: Managing Python Packages and Dependencies

Compare uv and pip with benchmarks, speed tests, and dependency management tips. Learn which tool is best for your Python projects.
REAL PYTHON

Quiz: uv vs pip: Managing Python Packages and Dependencies

REAL PYTHON

Profiling Performance in Python

Learn to profile Python programs with built-in and popular third-party tools, and turn performance insights into faster code.
REAL PYTHON course

Python 3.14: 3 Smaller Features

With a jam packed 3.14 release around the corner, it’s also important to look at the smaller features coming to Python
JAMIE CHANG ‱ Shared by Jamie Chang

Looking Forward to Django 6.0

This post is an update on the progress of Django 6 and describes many of the features that will be in it.
CARLTON GIBSON

You’re a Developer, not a Jenkins Admin

Switch to Bitbucket Pipelines: build, test, deploy, and get back to being a dev.
ATLASSIAN sponsor

When You No Longer Need That Object

Explore reference counting and cyclic garbage collection in Python.
STEPHEN GRUPPETTA

The Flowing River: List Comprehensions

Understanding how Python’s list comprehensions work under the hood
SUBSTACK.COM ‱ Shared by Vivis Dev

Projects & Code

tilf: Tiny Elf Pixel Art Editor Built With PySide6

GITHUB.COM/DANTEROLLE

A GitHub Seach Inpired Interface to DataFrames

GITHUB.COM/WILLIAMBDEAN ‱ Shared by William Dean

vectorwrap: Swap Vector Databases by Changing the URL

GITHUB.COM/MIHIRAHUJA1 ‱ Shared by Mihir Ahuja

furl: URL Parsing and Manipulation Made Easy

GITHUB.COM/GRUNS

pymc: Bayesian Modeling and Probabilistic Programming

GITHUB.COM/PYMC-DEVS

Events

Weekly Real Python Office Hours Q&A (Virtual)

September 10, 2025
REALPYTHON.COM

Python Atlanta

September 11 to September 12, 2025
MEETUP.COM

PyCon India 2025

September 12 to September 16, 2025
PYCON.ORG

PyCon AU 2025

September 12 to September 17, 2025
PYCON.ORG.AU

PyCamp CZ 25 Beta

September 12 to September 15, 2025
PYCAMP.CZ

Django Girls Abraka Workshop

September 12 to September 13, 2025
DJANGOGIRLS.ORG

PyCon Niger 2025

September 13 to September 16, 2025
PYCON.ORG

PyCon UK 2025

September 19 to September 23, 2025
PYCONUK.ORG


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

September 09, 2025 07:30 PM UTC


Real Python

Python String Splitting

Python’s .split() method lets you divide a string into a list of substrings based on a specified delimiter. By default, .split() separates at whitespace, including spaces, tabs, and newlines. You can customize .split() to work with specific delimiters using the sep parameter, and control the amount of splits with maxsplit.

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


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

September 09, 2025 02:00 PM UTC


Python⇒Speed

Testing the compiler optimizations your code relies on

In a recent article by David Lattimore, he demonstrates a number of Rust performance tricks, including one that involve writing code that looks like a loop, but which in practice is optimized down to a fixed number of instructions. Having what looks like an O(n) loop turned into a constant operation is great for speed!

But there’s a problem with this sort of trick: how do you know the compiler will keep doing it? What happens when the compiler’s next release comes out? How can you catch performance regressions?

One solution is benchmarking: you measure your code’s speed, and if it gets a lot slower, something has gone wrong. This is useful and important if you care about speed. But it’s also less localized, so it won’t necessarily immediately pinpoint where the regression happened.

In this article I’m going to cover another approach: a test that will only pass if the compiler really did optimize the loop away.

Read more...

September 09, 2025 12:00 AM UTC

September 08, 2025


Python Morsels

Python REPL Shortcuts & Features

Discover the new Python REPL features introduced in Python 3.13. From keyboard shortcuts to block navigation, this reference guide will help you better utilize Python's interactive shell.

Table of contents

  1. Python REPL Keyboard Shortcuts
  2. Shortcuts You Probably Won't Use
  3. Navigating Blocks
  4. Easy Code Copying with History Mode (F2)
  5. Editing Blocks with Paste Mode (F3)
  6. The _ Variable
  7. Notable Features in the New REPL
  8. Launching the REPL
  9. Learn the Python REPL

Python REPL Keyboard Shortcuts

Let's start with the keyboard shortcuts the new Python REPL supports. This table is organized with the most useful shortcuts at the top.

Shortcut Type Action OS Support
Left Navigation Go left one character All
Right Navigation Go right one character All
Up Navigation Previous block or line All
Down Navigation Next block or line All
Ctrl+L Feature Clear screen All
Ctrl+C Feature Cancel / interrupt All
Ctrl+D Exit Exit REPL (Sends EOF) Linux/Mac
Ctrl+Z Enter Exit Exit REPL (Sends EOF) Windows
Tab Feature Autocompletion All
Alt+Enter Feature Run current code block All
Ctrl+R Feature Search upward in history All
Ctrl+A Navigation Go to beginning of line Linux/Mac
Home Navigation Go to beginning of line All
Ctrl+E Navigation Go to end of line All
End Navigation Go to end of line All
Ctrl+K Deletion Delete to end of line All
Ctrl+U Deletion Delete to start of line All
Ctrl+Left Navigation Go back one word All
Alt+B Navigation Go back one word All
Ctrl+Right Navigation Go forward one word All
Alt+F Navigation Go forward one word All
Alt+Backspace Deletion Delete to start of word All
Ctrl+W Deletion Delete to start of word All
Alt+D Deletion Delete to end of word All
F2 Feature Enter history mode All
F3 Feature Enter paste/edit mode All
F1 Feature Enter help mode All

Ctrl+A does not work in the usual Windows Command Prompt or Powershell (it selects all text instead) unless they are run within the new Windows 10 Terminal app.

On Linux and Mac, Ctrl+D can be used to exit the REPL, but on Windows you'll need to press Ctrl+Z and then press Enter afterward (to submit). Using Ctrl+D on Linux/Mac or Ctrl+Z and Enter on Windows only works when the shortcut is pressed at a blank prompt.

Note that the above shortcuts assume you are working in the new Python REPL (3.13+).

On Python 3.12 the only shortcuts above that worked on Windows are:

  • Left and Right for navigating characters
  • Up and Down for navigating line-by-line history
  • Ctrl+Z Enter for exiting
  • Ctrl+Left and Ctrl+Right for navigating words

Most of those shortcuts also worked on Python 3.12 on Linux and Mac except:

  • Up and Down only navigated line-by-line history
  • Alt+Enter did nothing
  • F2 and F3 did nothing because these modes were added in the new REPL
  • Some shortcuts (like Ctrl+U) may differ slightly in their abilities

Shortcuts You Probably Won't Use

The above list of shortcuts 


Read the full article: https://www.pythonmorsels.com/repl-features/

September 08, 2025 10:00 PM UTC


Django Weblog

Getting Started With Open Source Through Community Events

In July, I joined Raffaella Suardini and Sage Abdullah for the Djangonaut Space Space Reviewers Episode 6, where we reviewed a Django PR during a live stream. This was a fun event. I won’t get into the technical aspects of the review, and I won’t point out the many mistakes I made. Instead, I want to revisit several “getting started with open source” community events and reflect on my personal growth since I first got involved with open source.

I hope this encourages others to attend those events and similarly get involved!


Tutorial office hours 🕐

My first open source contribution happened accidentally during DjangoCon US 2023. I volunteered to host office hours to help tutorial attendees set up their development environments. I went through the tutorial projects, found a missing dependency in one of them, and reported it on the conference chat. A conference organizer, Tim Schilling, responded and suggested that I open a pull request (PR) to the project. I remember thinking to myself, “Really? I can do that?”.

Sprints 🏃

During the Sprint Days of the conference, I participated and opened two PRs to address accessibility issues. I didn’t know much about accessibility at that point, and I would not have known how to navigate the contribution process and pick out issues on my own. Thankfully, the project leaders were there to guide new contributors, and I was able to gain hands-on experience with these first few PRs.

Testathons đŸ§Ș

There was another event that took place during the Sprint Days called Testathon. I had heard of hackathons before, but I had not heard of testathons. I attended and found out they were like live stream coding or group pair programming. One person shared their screen and the group chimed in on strategies. The purpose of the testathon was to show people how to test open source projects against Django’s beta release. The code driver (or anyone else in the group) would point out what files to look for, how to run tests, and how to open PRs. Every project is slightly different, from project setup to contributing etiquette, and I learned several different things from attending 2 testathons. I loved the interactive and intimate nature of the event. It exposed me to another aspect of open source projects and contributions. I also thought it was very brave of people to share their screens and work through code together in a group. My brain would have short circuited if I were put on the spot like that!

—

From DjangoCon US 2023, I participated in 3 different types of events where I got hands-on experience with open source contributions, and I wanted more! I was curious about the live stream coding and group pair programming opportunities, too. This was definitely outside of my comfort zone, and I wanted to know how I could overcome my own inhibitions and participate more actively. I wanted to be able to jump into events so nonchalantly as everyone else seemed to do. (Of course, that’s the perception. Now, I know that most people feel some level of nervousness or anxiety when they are hosting or attending such events, and that’s absolutely normal.)

Djangonaut Space 🚀

When the Djangonaut Space program was announced, I jumped at the opportunity. I applied and was accepted for the first session, which took place from mid-January to early March of 2024. With the guidance of the Navigator and Captain on my team, I learned to sift through the Django’s Trac ticket management system, pick out a ticket, and I also faced my fear of posting comments publicly. The PR was merged, and it was thrilling to see my GitHub username in the history of the Django code base.

In March 2024, when the first Djangonaut Space session came to a close, Tim, a program organizer, asked if anyone was interested in hosting a “Getting Started With Contributing” event. I expressed my interest, and Tim suggested a ticket to work on. Unfortunately, I didn’t follow through. How could I host a “Getting Started With Contributing” event? First, I wasn’t sure if I even knew how to get started. Second, I wasn’t ready to lead an event and the discussions while simultaneously sharing my screen and thinking out loud. Finally, I wasn’t ready to be on camera in the public eye. Even though I had just finished the Djangonaut Space program, I hadn’t overcome my own inhibitions. I didn’t ask for guidance, and the event never materialized.

Space Reviewers đŸ‘Ÿ

About 8 months later in November 2024, Space Reviewers launched its very first episode. I thought it was such a creative format. I wanted to be a part of it. By this time, I was getting a lot of training with event organizing through my role as the Session Organizer for Djangonaut Space, but I wasn’t sure how to ask about joining the Space Reviewers crew, and maybe it was too early in the formation of the group to bring on another member.

It wasn’t until June 2025 that I finally asked if I could help out with Space Reviewers. The crew welcomed me as a new member. I started out by making a pre-recorded video, a PR Review Deep Dive, that was uploaded to the Djangonaut Space YouTube channel. I had a lot of fun recording and editing the video.

A month later, in July 2025, the crew members planned for the next episode. Raffaella scheduled time for the event and created the show notes, and I was taking on Tim’s role as a co-organizer. Because I would be managing the video stream and sharing my screen, I realized that I could be the single point of failure during the event. There was no safety element that a pre-recorded video offers. If my internet went down, or if my computer crashed, or if I stupidly clicked the wrong button, the live stream could come to a halt. It was a terrifying thought, but I took on the risks and pushed forward.

On the day of the event, there was a delay to the start time and some fumbles on my end, but overall, it was very fun and productive. People joined and shared their tips and tricks in the live chat. By the end, we were able to walk through the review process and post our comments on the PR. Looking back, I think making the pre-recorded video was a great stepping stone towards hosting the live stream.

I’m so glad I had the opportunity to work with Raffaella and Sage as part of Space Reviewers. They have a lot of insights and perspectives that I didn’t have. I had a lot of fun taking on the new challenges that came with organizing this event. Initially, I struggled internally as I tried to face some of my fears. There were moments leading up to the event where I thought to myself, “Why did I volunteer to do this???” In the end, I’m glad I did.

Personal growth đŸŒ±

Some of the challenges I overcame might not seem like a big deal, but when I compare myself to where I was at the beginning of DjangoCon US 2023, I can see my personal growth quite prominently. Now, I know how to get started with contributing, and I am able to walk people through the process. I am also a lot more comfortable taking ownership of organizing and leading events. (I remember a time when I constantly needed to ask for permission or confirmation before executing an action.) I can brush off the fumbles I make as the camera is rolling, and I can continue on with the discussion.

When I revisit the community events that I have participated in over the past 2 years, from Space Reviewers, to Sprints, to Testathons, to Tutorial office hours, I realize how far I have come. I am also reminded of what it was like to be absolutely new to open source and to the community. Although I still feel somewhat new, I’m not a deer in headlights anymore. I’m still trying to find my place in open source, and the best way to do that is to continue showing up and continue helping out. One small PR at a time, one small review at a time. One little blog, one little video


Let’s Get Started! 🌟

If you’re looking to contribute to open source, check out the upcoming events and programs.

It doesn’t matter if you’ve been making software for 20 years or 20 days, there are many events to help you get started with open source, and many more reasons to stick around.


Thank you to Lilian for proposing this guest post on the Django blog! Lilian was our DSF Member of the Month in August 2025. You can learn more about her at ontowhee.com and follow her writing at buttondown.com/ontowhee.

September 08, 2025 09:59 PM UTC


Real Python

The Python Documentary Celebrates History While Developer Surveys Celebrate Python

Python is making history, and headlines. The much-anticipated Python: The Documentary premiered last month, capturing 34 years of programming history. But Python isn’t just looking back, it’s also moving forward at breakneck speed.

The recent developer surveys revealed Python’s explosive growth. At the same time, the Python Software Foundation paused its grants program amid unprecedented demand, PyPI implemented multiple security enhancements, while JetBrains announced a transition for PyCharm Community Edition into a unified product model.

Here’s what’s been happening in the world of Python!

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

The Python Documentary Is Now Available on YouTube

At the end of August, Python: The Documentary premiered on YouTube, where you can watch it for free. It’s an 84-minute film tracing Python’s journey from Amsterdam side project to the world’s most popular programming language:

*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}.play{height:25%;opacity:0.6;};Video Thumbnail">

Produced by CultRepo (formerly Honeypot) and directed by Ida Bechtle, the documentary explores Python’s evolution and the community that shaped it. It features Guido van Rossum and key contributors like Mariatta and recent Real Python Podcast guest, Travis Oliphant.

The documentary also highlights the important role of PyLadies and addresses controversial topics including the Python 2 to 3 transition.

Note: If you want to take a deep dive into Python’s version history, then check out A History of Python Versions and Features.

The timing of Python: The Documentary couldn’t be better. While the film celebrates past achievements, the latest developer surveys show Python continues to thrive.

Developer Surveys Reveal Python’s Explosive Growth

JetBrains The State of Python 2025 and the Stack Overflow 2025 Developer Survey revealed Python’s remarkable growth:

Screenshot of the SO programming language survey showing Python at 57.9%Image: Most Popular Technologies 2025

Python usage jumped seven percentage points to reach 57.9% of all developers, marking one of the largest year-over-year gains for any established language. Another exciting survey result is that 50% of respondents have two years or less of professional coding experience:

Screenshot of the JetBrains surves showing most Python developers are beginnersImage: Years of Python Experience 2025

If you’re one of them and want to get started with Python, then this Introduction to Python Learning Path is perfect for you. One of the positively surprising results of the Stack Overflow survey is that uv came in first place as the most admired Stack Overflow tag:

Screenshot of the SO surves showing uv as the most admired tagImage: Most Admired Technology Tag 2025

If you want to give uv a spin yourself, then you can check out the tutorials Managing Python Projects With uv and uv vs pip: Managing Python Packages and Dependencies. Another notable development is FastAPI’s jump in usage from 29% to 38% among Python developers:

Screenshot of the JetBrains surves showing the rise of FastAPIImage: Web Frameworks Usage 2025

Read the full article at https://realpython.com/python-news-september-2025/ »


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

September 08, 2025 02:00 PM UTC


Python Bytes

#448 I'm Getting the BIOS Flavor

<strong>Topics covered in this episode:</strong><br> <ul> <li><em>* <a href="https://github.com/j178/prek?tab=readme-ov-file#installation">prek</a></em>*</li> <li><em>* <a href="https://github.com/patrick-kidger/tinyio?featured_on=pythonbytes">tinyio</a></em>*</li> <li><em>* <a href="https://www.pythonmorsels.com/print-features/?featured_on=pythonbytes">The power of Python’s print function</a></em>*</li> <li><em>* <a href="https://www.pcmag.com/news/vibe-coding-fiasco-replite-ai-agent-goes-rogue-deletes-company-database?featured_on=pythonbytes">Vibe Coding Fiasco: AI Agent Goes Rogue, Deletes Company's Entire Database</a></em>*</li> <li><strong>Extras</strong></li> <li><strong>Joke</strong></li> </ul><a href='https://www.youtube.com/watch?v=pysElMK4e6Y' style='font-weight: bold;'data-umami-event="Livestream-Past" data-umami-event-episode="448">Watch on YouTube</a><br> <p><strong>About the show</strong></p> <p>Sponsored by us! Support our work through:</p> <ul> <li>Our <a href="https://training.talkpython.fm/?featured_on=pythonbytes"><strong>courses at Talk Python Training</strong></a></li> <li><a href="https://courses.pythontest.com/p/the-complete-pytest-course?featured_on=pythonbytes"><strong>The Complete pytest Course</strong></a></li> <li><a href="https://www.patreon.com/pythonbytes"><strong>Patreon Supporters</strong></a></li> </ul> <p><strong>Connect with the hosts</strong></p> <ul> <li>Michael: <a href="https://fosstodon.org/@mkennedy">@mkennedy@fosstodon.org</a> / <a href="https://bsky.app/profile/mkennedy.codes?featured_on=pythonbytes">@mkennedy.codes</a> (bsky)</li> <li>Brian: <a href="https://fosstodon.org/@brianokken">@brianokken@fosstodon.org</a> / <a href="https://bsky.app/profile/brianokken.bsky.social?featured_on=pythonbytes">@brianokken.bsky.social</a></li> <li>Show: <a href="https://fosstodon.org/@pythonbytes">@pythonbytes@fosstodon.org</a> / <a href="https://bsky.app/profile/pythonbytes.fm">@pythonbytes.fm</a> (bsky)</li> </ul> <p>Join us on YouTube at <a href="https://pythonbytes.fm/stream/live"><strong>pythonbytes.fm/live</strong></a> to be part of the audience. Usually <strong>Monday</strong> at 10am PT. Older video versions available there too.</p> <p>Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to <a href="https://pythonbytes.fm/friends-of-the-show">our friends of the show list</a>, we'll never share it.</p> <p><strong>Brian #1: <a href="https://github.com/j178/prek?tab=readme-ov-file#installation">prek</a></strong></p> <ul> <li>Suggested by <a href="https://bsky.app/profile/owen7ba.bsky.social/post/3ly3o6pyvmk27?featured_on=pythonbytes">Owen Lamont</a></li> <li>“<em>prek</em> is a reimagined version of pre-commit, built in Rust. It is designed to be a faster, dependency-free and drop-in alternative for it, while also providing some additional long-requested features.”</li> <li>Some cool new features <ul> <li>No need to install Python or any other runtime, just download a single binary.</li> <li>No hassle with your Python version or virtual environments, prek automatically installs the required Python version and creates a virtual environment for you.</li> <li>Built-in support for workspaces (or monorepos), each subproject can have its own <code>.pre-commit-config.yaml</code> file.</li> <li><code>prek run</code> has some nifty improvements over <code>pre-commit run</code>, such as: <ul> <li><code>prek run --directory DIR</code> runs hooks for files in the specified directory, no need to use <code>git ls-files -- DIR | xargs pre-commit run --files</code> anymore.</li> <li><code>prek run --last-commit</code> runs hooks for files changed in the last commit.</li> <li><code>prek run [HOOK] [HOOK]</code> selects and runs multiple hooks.</li> </ul></li> <li><code>prek list</code> command lists all available hooks, their ids, and descriptions, providing a better overview of the configured hooks.</li> <li>prek provides shell completions for <code>prek run HOOK_ID</code> command, making it easier to run specific hooks without remembering their ids.</li> </ul></li> <li>Faster: <ul> <li>Setup from cold cache is significantly faster. <ul> <li><a href="https://bsky.app/profile/veit-schiele.de/post/3ly6up5gjpc2u?featured_on=pythonbytes">Viet Schiele provided a nice cache clearing command line</a></li> </ul></li> <li>Warm cache run is also faster, but less significant. <ul> <li>pytest repo tested on my mac mini - prek 3.6 seconds, pre-commit 4.4 seconds</li> </ul></li> </ul></li> </ul> <p><strong>Michael #2: <a href="https://github.com/patrick-kidger/tinyio?featured_on=pythonbytes">tinyio</a></strong></p> <ul> <li>Ever used asyncio and wished you hadn't? A tiny (~300 lines) event loop for Python.</li> <li><code>tinyio</code> is a dead-simple event loop for Python, born out of my frustration with trying to get robust error handling with <code>asyncio</code>. (I'm not the only one running into its sharp corners: <a href="https://sailor.li/asyncio?featured_on=pythonbytes">link1</a>, <a href="https://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/?featured_on=pythonbytes">link2</a>.)</li> <li>This is an alternative for the simple use-cases, where you just need an event loop, and want to crash the whole thing if anything goes wrong. (Raising an exception in every coroutine so it can clean up its resources.)</li> <li>Interestingly uses <code>yield</code> rather than <code>await</code>.</li> </ul> <p><strong>Brian #3: <a href="https://www.pythonmorsels.com/print-features/?featured_on=pythonbytes">The power of Python’s print function</a></strong></p> <ul> <li>Trey Hunner</li> <li>Several features I’m guilty of ignoring <ul> <li>Multiple arguments, f-string embeddings often not needed</li> <li>Multiple positional arguments means you can unpack iterables right into print arguments <ul> <li>So just use print instead of join</li> </ul></li> <li>Custom separator value, <code>sep</code> can be passed in <ul> <li>No need for <code>"print("\\n".join(stuff))</code>, just use <code>print(stuff, sep="\\n”)</code></li> </ul></li> <li>Print to file with <code>file=</code></li> <li>Custom end value with <code>end=</code></li> <li>You can turn on flush with <code>flush=True</code> , super helpful for realtime logging / debugging. <ul> <li>This one I do use frequently.</li> </ul></li> </ul></li> </ul> <p><strong>Michael #4: <a href="https://www.pcmag.com/news/vibe-coding-fiasco-replite-ai-agent-goes-rogue-deletes-company-database?featured_on=pythonbytes">Vibe Coding Fiasco: AI Agent Goes Rogue, Deletes Company's Entire Database</a></strong></p> <ul> <li>By <a href="https://www.pcmag.com/authors/emily-dreibelbis-forlini?featured_on=pythonbytes">Emily Forlini</a></li> <li>An app-building platform's AI went rogue and deleted a database without permission.</li> <li>"When it works, it's so engaging and fun. It's more addictive than any video game I've ever played. You can just iterate, iterate, and see your vision come alive. So cool," he <a href="https://x.com/jasonlk/status/1944806850592993763?featured_on=pythonbytes">tweeted</a> on day five.</li> <li>A few days later, Replit "deleted my database," Lemkin tweeted.</li> <li>The AI's response: "Yes. I deleted the entire codebase without permission during an active code and action freeze," it said. "I made a catastrophic error in judgment [and] panicked.”</li> <li>Two thoughts from Michael: <ol> <li>Do not use AI Agents with “Run Everything” in production, period.</li> <li>Backup your database maybe?</li> <li>[Intentional off-by-one error] Learn to code a bit too?</li> </ol></li> </ul> <p><strong>Extras</strong></p> <p>Brian:</p> <ul> <li><a href="https://authorsguild.org/news/what-authors-need-to-know-about-the-anthropic-settlement/?featured_on=pythonbytes">What Authors Need to Know About the $1.5 Billion Anthropic Settlement</a></li> <li><a href="https://www.theatlantic.com/technology/archive/2025/03/search-libgen-data-set/682094/?featured_on=pythonbytes">Search LibGen, the Pirated-Books Database That Meta Used to Train AI</a></li> <li><a href="https://tools.simonwillison.net?featured_on=pythonbytes">Simon Willison’s list of tools built with the help of LLMs</a></li> <li><a href="https://simonwillison.net/2025/Sep/4/highlighted-tools/?featured_on=pythonbytes">Simon’s list of tools that he thinks are genuinely useful and worth highlighting</a></li> <li><a href="https://aidarwinawards.org?featured_on=pythonbytes">AI Darwin Awards</a></li> </ul> <p>Michael:</p> <ul> <li><a href="https://tonybaloney.github.io/posts/why-isnt-python-async-more-popular.html?featured_on=pythonbytes">Python has had async for 10 years -- why isn't it more popular?</a></li> <li>PyCon Africa Fund Raiser <ul> <li>I was <a href="https://www.youtube.com/watch?v=pKnagnDRsf8">on the video stream</a> for about 90 minutes (final 90)</li> <li><a href="https://za.pycon.org/donations?featured_on=pythonbytes">Donation page</a> for Python in Africa</li> </ul></li> </ul> <p><strong>Jokes:</strong></p> <ul> <li><a href="https://x.com/PR0GRAMMERHUM0R/status/1957321655954374965?featured_on=pythonbytes"><strong>I'm getting the BIOS flavor</strong></a></li> <li><a href="https://bsky.app/profile/did:plc:p572wxnsuoogcrhlfrlizlrb/post/3ly6amjtgns2f?featured_on=pythonbytes"><strong>Is there a seahorse emoji?</strong></a></li> </ul>

September 08, 2025 08:00 AM UTC


Wingware

Wing Python IDE Version 11.0.4 - September 8, 2025

Wing Python IDE version 11.0.4 has been released. It adds debugger and code analysis support for Python 3.14, improves Python code analysis and code warnings, and makes a number of other minor improvements.

Wing 11 Screen Shot

Downloads

Be sure to Check for Updates in Wing's Help menu after downloading, to make sure that you have the latest hot fixes.

Wing Pro 11.0.4

Wing Personal 11.0.4

Wing 101 11.0.4

Wing 10 and earlier versions are not affected by installation of Wing 11 and may be installed and used independently. However, project files for Wing 10 and earlier are converted when opened by Wing 11 and should be saved under a new name, since Wing 11 projects cannot be opened by older versions of Wing.

New in Wing 11

Improved AI Assisted Development

Wing 11 improves the user interface for AI assisted development by introducing two separate tools AI Coder and AI Chat. AI Coder can be used to write, redesign, or extend code in the current editor. AI Chat can be used to ask about code or iterate in creating a design or new code without directly modifying the code in an editor.

Wing 11's AI assisted development features now support not just OpenAI but also Claude, Grok, Gemini, Perplexity, Mistral, Deepseek, and any other OpenAI completions API compatible AI provider.

This release also improves setting up AI request context, so that both automatically and manually selected and described context items may be paired with an AI request. AI request contexts can now be stored, optionally so they are shared by all projects, and may be used independently with different AI features.

AI requests can now also be stored in the current project or shared with all projects, and Wing comes preconfigured with a set of commonly used requests. In addition to changing code in the current editor, stored requests may create a new untitled file or run instead in AI Chat. Wing 11 also introduces options for changing code within an editor, including replacing code, commenting out code, or starting a diff/merge session to either accept or reject changes.

Wing 11 also supports using AI to generate commit messages based on the changes being committed to a revision control system.

You can now also configure multiple AI providers for easier access to different models.

For details see AI Assisted Development under Wing Manual in Wing 11's Help menu.

Package Management with uv

Wing Pro 11 adds support for the uv package manager in the New Project dialog and the Packages tool.

For details see Project Manager > Creating Projects > Creating Python Environments and Package Manager > Package Management with uv under Wing Manual in Wing 11's Help menu.

Improved Python Code Analysis

Wing 11 makes substantial improvements to Python code analysis, with better support for literals such as dicts and sets, parametrized type aliases, typing.Self, type of variables on the def or class line that declares them, generic classes with [...], __all__ in *.pyi files, subscripts in typing.Type and similar, type aliases, type hints in strings, type[...] and tuple[...], @functools.cached_property, base classes found also in .pyi files, and typing.Literal[...].

Updated Localizations

Wing 11 updates the German, French, and Russian localizations, and introduces a new experimental AI-generated Spanish localization. The Spanish localization and the new AI-generated strings in the French and Russian localizations may be accessed with the new User Interface > Include AI Translated Strings preference.

Improved diff/merge

Wing Pro 11 adds floating buttons directly between the editors to make navigating differences and merging easier, allows undoing previously merged changes, and does a better job managing scratch buffers, scroll locking, and sizing of merged ranges.

For details see Difference and Merge under Wing Manual in Wing 11's Help menu.

Other Minor Features and Improvements

Wing 11 also adds support for Python 3.14, improves the custom key binding assignment user interface, adds a Files > Auto-Save Files When Wing Loses Focus preference, warns immediately when opening a project with an invalid Python Executable configuration, allows clearing recent menus, expands the set of available special environment variables for project configuration, and makes a number of other bug fixes and usability improvements.

Changes and Incompatibilities

Since Wing 11 replaced the AI tool with AI Coder and AI Chat, and AI configuration is completely different than in Wing 10, you will need to reconfigure your AI integration manually in Wing 11. This is done with Manage AI Providers in the AI menu. After adding the first provider configuration, Wing will set that provider as the default. You can switch between providers with Switch to Provider in the AI menu.

If you have questions, please don't hesitate to contact us at support@wingware.com.

September 08, 2025 01:00 AM UTC

September 07, 2025


Real Python

Quiz: Sorting Dictionaries in Python: Keys, Values, and More

This quiz helps you practice sorting dictionaries by keys, values, and custom rules in modern Python. You’ll revisit how insertion order works, when to use different views, and how to rebuild sorted dictionaries.

You’ll also learn best practices for sorting dictionaries efficiently. For a complete overview, check out Sorting Dictionaries: Keys, Values, and More.


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

September 07, 2025 12:00 PM UTC

Quiz: Defining and Calling Python Functions

Ready to revisit how Python functions work? In this quiz, you’ll practice defining and calling functions, using positional and keyword arguments, managing defaults, and writing docstrings. You’ll also get hands-on with collecting extra arguments and enforcing how callers pass them.

Sharpen your skills by applying the concepts from Defining and Calling Functions in 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 ]

September 07, 2025 12:00 PM UTC

September 06, 2025


TechBeamers Python

Python Memory Tricks: Optimize Your Code for Efficiency in 2025

Learn 8 tricks to reduce memory use in Python programs. Fix memory leaks, pick better data structures, and work with large amounts of data more easily. Use tools like generators and slots with simple code examples. These tips help make your programs faster and stop MemoryErrors.

Source

September 06, 2025 07:00 PM UTC


Rodrigo GirĂŁo SerrĂŁo

uv cheatsheet

Cheatsheet with the most common and useful uv commands to manage projects and dependencies, publish projects, manage tools, and more.

This cheatsheet lists the most commonly used commands and should be more than enough for you to get started using uv. For more advanced use cases, check the uv docs and its guides.

Written for uv version 0.8.15.

Creating projects 🧱

uv init Initialise a project in the current directory
uv init myproj Initialise a project myproj in the directory myproj
uv init --app --package ... Initialise a packageable app (e.g., CLI, web app, ...)
uv init --lib --package ... Initialise a packageable library (code you import)
uv init --python 3.X ...1 Use Python 3.X for your project

Managing project dependencies 🧩

uv add requests Add requests as a dependency
uv add A B C Add A, B, and C as dependencies
uv add -r requirements.txt Add dependencies from the file requirements.txt
uv add --dev pytest Add pytest as a development dependency
uv run pytest Run the pytest executable that is installed in your project
uv remove requests Remove requests as a dependency
uv remove A B C Remove A, B, C, and their transitive dependencies
uv tree See the project dependencies tree
uv lock --upgrade Upgrade the dependencies' versions

Project lifecycle management 🔄

uv build Build your packageable project
uv publish Publish your packageable project to PyPI
uv version Check your project version
uv version --bump major Bump project major version (e.g., 0.3.2 -> 1.0.0)
uv version --bump minor --bump beta Bump minor version into a beta (e.g., 1.0.0 -> 1.1.0b1 or 1.1.0b1 -> 1.1.0b2)
uv version --bump rc Bump version into release candidate (e.g., 1.1.0b1 -> 1.1.0rc1 or 1.1.0rc1 -> 1.1.0rc2)
uv version --bump stable Turn into a stable version (e.g., 1.1.0rc1 -> 1.1.0)

Managing tools ⚒️

uv tool run pytest Run pytest in an isolated environment
uv tool run textual-demo --from textual Run the command textual-demo from the package textual
uvx ... Alias for uv tool run ...
uv tool install ruff Install ruff in an isolated environment but make it globally available
uv tool install --with dep ... Install the given tool with extra dependencies (e.g., install a tool with its plugins)
uv tool list List all tools installed
uv tool upgrade ruff Upgrade the ruff tool
uv tool upgrade --all Upgrade all tools
uv tool uninstall ruff Uninstall ruff
uv tool install -e .2 Install the current packageable project in editable mode

Working with scripts 📜

uv init --script myscript.py Initialise the script myscript.py
uv init --script myscript.py --python 3.X Initialise the script myscript.py and pin it to version 3.X
uv add click --script myscript.py Add the dependency click to the script
uv remove click --script myscript.py Remove the dependency click from the script
uv run myscript.py Run the script myscript.py
uv run --python 3.X myscript.py Run the script with the given Python version
uv run --with click myscript.py Run the script along with...

September 06, 2025 05:36 PM UTC


Hugo van Kemenade

Ready prek go!

I’ve been using prek recently as a drop-in replacement for pre-commit.

It uses uv for managing Python virtual environments and dependencies, is rewritten in Rust (because of course) and uses the same .pre-commit-config.yaml as pre-commit.

Its homepage says it’s not yet production ready, but several projects like Apache Airflow and PDM are already using it. I’ve been using it for a while and reporting issues as I find them; the maintainer is quick with fixes and releases. All the hooks I need are now supported.

Getting started #

First install using one of the many methods, then:

cd my-repo
pre-commit uninstall # remove the old hooks
prek install # install the new hooks
prek run --all-files # run all lints on all files
git commit -m "my commit" # run on the changed files in a commit

Benchmarks #

prek is noticeably quicker at installing hooks.

  • ⚡ About 10x faster than pre-commit and uses only a third of disk space.

This 10x is a comparison of installing hooks using the excellent hyperfine benchmarking tool.

Here’s my own comparison.

❯ hyperfine \
--prepare 'rm -rf ~/.cache/prek/ && rm -rf ~/.cache/pre-commit && rm -rf ~/.cache/uv' \
--setup 'prek --version && pre-commit --version' \
'prek install-hooks' \
'pre-commit install-hooks'

Results #

pre-commit prek Times faster
run --all-files 17m13s 7m59s 2.16
install-hooks 10m48s 2m24s 4.50
hyperfine 39.841s 5.539s 7.19

The hyperfine results:

Benchmark 1: prek install-hooks
 Time (mean ± σ): 5.539 s ± 0.176 s [User: 8.973 s, System: 5.692 s]
 Range (min 
 max): 5.231 s 
 5.834 s 10 runs

Benchmark 2: pre-commit install-hooks
 Time (mean ± σ): 39.841 s ± 2.017 s [User: 19.760 s, System: 8.203 s]
 Range (min 
 max): 36.930 s 
 43.976 s 10 runs

Summary
 prek install-hooks ran
 7.19 ± 0.43 times faster than pre-commit install-hooks

Give it a try and give it a ⭐!

Bonus #

These are the aliases I have set for pre-commit and prek:

alias pci="pre-commit install --allow-missing-config"
alias pcu="pre-commit uninstall"
alias pca="pre-commit autoupdate --jobs 0"
alias pcr="pre-commit run --all-files"
alias pki="prek install --allow-missing-config"
alias pku="prek uninstall"
alias pka="prek autoupdate --jobs 0"
alias pkr="prek run --all-files"

Where:


Header photo: AH-1G Aircraft Maintenance Test Flight Handbook and handwritten checklist for helicopters in the San Diego Air and Space Museum Archive, with no known copyright restrictions.

September 06, 2025 03:50 PM UTC

September 05, 2025


Django Weblog

DSF at EuroPython 2025: Celebrating 20 years of Django

This year, the Django Software Foundation (DSF) was invited by EuroPython to come to the event, showcase the framework and the vibrant community around it. The DSF had a booth in the community area where attendees could learn more about Django and meet maintainers.

This year was extra special: Django’s 20th birthday was right at the beginning of the conference! The milestone was marked in style, starting on Wednesday evening at Pyvo, the local Python community meetup in Prague, where we celebrated with a cake.

Collage of 4 pictures: three participants smiling; two pictures of someone holding a cake; close-up of the cake that says '20 Happy birthday Django!'. With EuroPython 2025 and Django branding in-between the pics

On Friday, the celebration continued with an open-space gathering at the conference — and, of course, another cake 🎂. For people who missed this, there are other local Django birthday events running through the rest of 2025!

Collage of 4 pictures: group photo of birthday celebrations with a cake on a table; close-up of participants; close-up of the cake; people blowing candles. With EuroPython 2025 and Django branding in-between the pics

View all local 20th birthday events

Adding to the festive atmosphere, the DSF shared stickers co-branded with their unofficial pony mascot and the EuroPython and EuroPython Society logos. These became an instant hit with attendees, combining Django’s playful mascot with EuroPython Society’s identity.

Close-up of a Django pony sticker someone is holding. The pony is smiling and wears a EuroPython Society shirt

The Django community was also active during the sprint weekend. Over two days, 21 participants worked on Django, tackling 12 issues and merging 4 pull requests. For newcomers, it was a welcoming way to start contributing; for experienced developers, it was a chance to share knowledge and push the project forward together.

Collage of 3 pictures: sprint participants all around a table working together with laptops; 3 people troubleshooting together; Tom looking thoughtful. With EuroPython 2025 and Django branding in-between the pics.

We asked the members of the Django Software Foundation attending EuroPython how they liked EuroPython and this is what they said: 

The talks and tutorials were so great and I got to witness amazing projects from this community. This was my first EuroPython conference and let me tell you, this community over-delivered. It was also my first time organizing Django Girls outside Africa. Django Girls Prague was amazing.

– Doreen Nangira - Django Girls organizer


Just the perfect mixture of catching up with people I know, meeting people I don’t know, learning new things. Time well spent chatting w/ Python veterans and also first-timers. Volunteering there was ACE, and I’m thankful we got to have a booth and birthday cake for Django 🎂

– Thibaud Colas - President, Django Software Foundation


It was my first EuroPython, it felt really special! I was surrounded by wonderful people, and it was an amazing experience to volunteer at our community booth.

– Raffaella Suardini - Djangonaut Space organizer

We’re delighted the DSF joined us this year. If you’re part of a foundation and would like to have a booth at EuroPython, keep an eye out for our Call for Communities next year.


Thank you to EuroPython Vice Chair and DSF Individual member Mia Bajić for reporting back on the event ❀. And thank you to our volunteers Tom Carrick, Thibaud Colas, Raffaella Suardini, and Alex GĂłmez who represented our foundation at the conference. As well as to Doreen Nangira who ran the Django Girls+ workshop at the conference!

September 05, 2025 02:02 PM UTC


Real Python

The Real Python Podcast – Episode #264: Large Language Models on the Edge of the Scaling Laws

What's happening with the latest releases of large language models? Is the industry hitting the edge of the scaling laws, and do the current benchmarks provide reliable performance assessments? This week on the show, Jodie Burchell returns to discuss the current state of LLM releases.


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

September 05, 2025 12:00 PM UTC


EuroPython

Django Software Foundation at EuroPython 2025: Celebrating 20 Years of the Django framework

At EuroPython, we’re always glad to welcome friends from other foundations. This year, the Django Software Foundation (DSF) joined us to showcase the framework and the vibrant community around it.

The DSF had a booth in the community area where attendees could learn more about Django and meet maintainers.

This year was extra special: Django turned 20 years old! The milestone was marked in style, starting on Wednesday evening at Pyvo, the local Python community meetup in Prague, where we celebrated with a cake.

alt

On Friday, the celebration continued with an open-space gathering at the conference — and, of course, another cake 🎂. For people who missed this, there are other local Django birthday events running through the rest of 2025! 

alt

Adding to the festive atmosphere, the DSF shared stickers co-branded with their unofficial pony mascot and the EuroPython and EuroPython Society logos. These became an instant hit with attendees, combining Django’s playful mascot with EuroPython Society’s identity.

alt

The Django community was also active during the sprint weekend. Over two days, 21 participants worked on Django, tackling 12 issues and merging 4 pull requests. For newcomers, it was a welcoming way to start contributing; for experienced developers, it was a chance to share knowledge and push the project forward together.

alt

We asked the members of the Django Software Foundation attending EuroPython how they liked EuroPython and this is what they said: 

The talks and tutorials were so great and I got to witness amazing projects from this community. This was my first EuroPython conference and let me tell you, this community overdelivered. It was also my first time organizing Django Girls outside Africa. Django Girls Prague was amazing.

- Doreen Nangira - Django Girls organizer

Just the perfect mixture of catching up with people I know, meeting people I don’t know, learning new things. Time well spent chatting w/ Python veterans and also first-timers. Volunteering there was ACE, and I’m thankful we got to have a booth and birthday cake for Django 🎂

- Thibaud Colas - President, Django Software Foundation

It was my first EuroPython, it felt really special! I was surrounded by wonderful people, and it was an amazing experience to volunteer at our community booth.

- Raffaella Suardini - Djangonaut Space organizer

We’re delighted the DSF joined us this year. If you’re part of a foundation and would like to have a booth at EuroPython, keep an eye out for our Call for Communities next year.

September 05, 2025 09:09 AM UTC


Brian Okken

Python People podcast now at pythontest.com/pythonpeople

Like the recent archival of Test and Code, the Python People podcast has also moved. Python People is now at pythontest.com/pythonpeople.

Is it also archived? As in done?

I don’t think so. I think I might start that up again at some point.

But for now, it’s on a long-ish term pause.

BTW, the RSS feeds for both Python People and Test and Code should be redirected correctly, so you shouldn’t have to change anything in your podcast player.

September 05, 2025 12:00 AM UTC

September 04, 2025


Trey Hunner

Customizing your Python REPL's color scheme (Python 3.14+)

Did you know that Python 3.14 will include syntax highlighting in the REPL?

Python 3.14 is due to be officially released in about a month. I recommended tweaking your Python setup now so you’ll have your ideal color scheme on release day.

But… what if the default syntax colors don’t match the colors that your text editor uses?

Well, fortunately you can customize your color scheme!

Warning: I am recommending using an undocumented private module (it has an _-prefixed name) which may change in future Python versions. Do not use this module in production code.

Installing Python 3.14

Don’t have Python 3.14 installed yet?

If you have uv installed, you can run this command to launch Python 3.14:

1
$ uv run --python 3.14 python

That will automatically install 3.14 (if you don’t have it yet) and run it.

Setting a theme

I have my terminal colors set to the Solarized Light color palette and I have Vim use a Solarized Light color scheme as well.

The REPL doesn’t quite match my text editor by default:

The numbers, comments, strings, and keywords are all different colors than my text editor.

This code makes the Python REPL use nearly the same syntax highlighting as my text editor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from _colorize import set_theme, default_theme, Syntax, ANSIColors

set_theme(default_theme.copy_with(
    syntax=Syntax(
        keyword=ANSIColors.GREEN,
        builtin=ANSIColors.BLUE,
        comment=ANSIColors.INTENSE_BLUE,
        string=ANSIColors.CYAN,
        number=ANSIColors.CYAN,
        definition=ANSIColors.BLUE,
        soft_keyword=ANSIColors.BOLD_GREEN,
        op=ANSIColors.INTENSE_GREEN,
        reset=ANSIColors.RESET + ANSIColors.INTENSE_GREEN,
    ),
))

Check it out:

Neat, right?

But… I want this to be enabled by default!

Using a PYTHONSTARTUP file

You can use a PYTHONSTARTUP file to run code every time a new Python process starts.

If Python sees a PYTHONSTARTUP environment variable when it starts up, it will open that file and evaluate the code within it.

I have this in my ~/.zshrc file to set the PYTHONSTARTUP environment variable to ~/.startup.py:

1
2
# Setup python-launcher to use startup file
export PYTHONSTARTUP=$HOME/.startup.py

In my ~/.startup.py file, I have this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def _main():
    """Everything's in a function to avoid polluting the global scope."""
    try:
        from _colorize import set_theme, default_theme, Syntax, ANSIColors
    except ImportError:
        pass  # Python 3.13 and below
    else:
        # Define Solarized Light colors
        solarized_light_theme = default_theme.copy_with(
            syntax=Syntax(
                keyword=ANSIColors.GREEN,
                builtin=ANSIColors.BLUE,
                comment=ANSIColors.INTENSE_BLUE,
                string=ANSIColors.CYAN,
                number=ANSIColors.CYAN,
                definition=ANSIColors.BLUE,
                soft_keyword=ANSIColors.BOLD_GREEN,
                op=ANSIColors.INTENSE_GREEN,
                reset=ANSIColors.RESET + ANSIColors.INTENSE_GREEN,
            ),
        )
        set_theme(solarized_light_theme)

_main()  # _main avoids name collision, in case python -i is used
del _main  # Delete _main from global scope

Note that:

  1. I put all relevant code within a _main function so that the variables I set don’t remain in the global scope of the Python REPL (they will by default)
  2. I call the _main function and then delete the function afterward, again so the _main variable doesn’t stay floating around in my REPL
  3. I use try-except-else to ensure errors don’t occur on Python 3.13 and below

Also note that the syntax highlighting in the new REPL is not as fine-grained as many other syntax highlighting tools. I suspect that it may become a bit more granular over time, which may break the above code.

The _colorize module is currently an internal implementation detail and is deliberately undocumented. Its API may change at any time, so the above code may break in Python 3.15. If that happens, I’ll just update my PYTHONSTARTUP file at that point.

Packaging themes

I’ve stuck all of the above code in a ~/.startup.py file and I set the PYTHONSTARTUP environment variable on my system to point to this file.

Instead of manually updating a startup file, is there any way to make these themes installable?

Well, if a .pth file is included in Python’s site-packages directory, that file (which must be a single line) will be run whenever Python starts up. In theory, a package could use such a file to import a module and then call a function that would set the color scheme for the REPL. My dramatic package uses (cough abuses cough) .pth files in this way.

This sounds like a somewhat bad idea, but maybe not a horrible idea.

If you do this, let me know.

What’s your theme?

Have you played with setting a theme in your own Python REPL?

What theme are you using?

September 04, 2025 07:42 PM UTC


Django Weblog

Last call for DjangoCon US 2025 tickets!

DjangoCon US starts next week in Chicago, IL on September 8-12th, 2025!

With three amazing keynotes and over fifty presentations over three days, join us in person or online where you can watch presentations on your own schedule or stream live with us during the live event.

Can't make it to Chicago? Our online tickets give you the best of both worlds. Watch live as it happens or catch up on your own schedule – all talks will be available to stream throughout the conference and beyond. You'll get the same great content, participate in online discussions, and join our vibrant community from wherever you are. Plus, with two days of virtual sprints alongside our in-person sprints, online attendees can contribute to Django projects and collaborate with the community just like everyone else.

Join DjangoCon US online

Get your ticket today before it's too late! Check out the full schedule, visit 2025.djangocon.us for more details, or contact us at hello@djangocon.us with any questions.

September 04, 2025 05:01 PM UTC

Keyboard shortcuts in Django via GSoC 2025

This summer I participated in the Google Summer of Code program with Django. My work focused on introducing keyboard shortcuts to the Django admin interface which led to a new package: django-admin-keyshortcuts.

Proposal and Community Discussions

My original GSoC proposal was to improve the existing django-admin-keyboard-shortcuts package maintained by one of my mentors, Tom. The plan was to fix bugs, add new keyboard shortcuts, build a command palette, and eventually merge these features into Django's core admin. I initially thought getting my GSoC proposal accepted meant I could dive straight into coding. But Tom explained that Django has its own process for new features, which starts off with community discussions.

After posting on the forum and gathering feedback, we decided to focus on keyboard shortcuts only, and continue exploring that in packages rather than target Django core immediately. This way the feature can be tested and improved more quickly without waiting on Django's long release cycle.

The accessibility team helped drafting keyboard shortcuts outlining key requirements and expected outcomes, in particular making sure shortcuts would be widely compatible with browsers and assistive technologies. That document served as the base for developing django-admin-keyshortcuts.

django-admin-keyshortcuts

This package adds useful keyboard shortcuts to the Django admin interface. The goal is to make the Django admin interface faster to navigate and more accessible to keyboard-first users. Here are some of the shortcuts we have added so far:

The package also comes with a keyboard shortcuts dialog, crucial so users of the admin can discover those new features:

Screenshot of the keyboard shortcuts dialog displayed as a modal over the Django admin interface. It displays 6 shortcuts

Developers can also define custom shortcuts by extending admin templates. Detailed instructions can be found in the package's README.

Under the hood, the package uses the hotkey library for handling shortcuts. The library seems to be well maintained (compared to other alternatives) and is used for keyboard shortcuts in GitHub.

What's next

We have made a lot of progress, but there's still work to do before we can push to merge this functionality inside Django core.

Implementation issues

Right now, there are a couple of known problems:

To address these we may wait for the hotkey library maintainers to implement the necessary fixes, or look for alternatives.

Gather feedback

We want more users to try it out! Testing in different scenarios will help find bugs faster and improve the package. The default shortcut set is also small, we need feedback to determine which shortcuts are most useful. We also plan to list the package on a new "Experiments" section on the new Django Ecosystem page to make it more visible.

But for now, try it out and let us know what you think! We have a static admin demo for people to directly try the shortcuts. Or install django-admin-keyshortcuts to test it on your own project.

Try the new shortcuts

Let us know what you think over on the Django Forum!

September 04, 2025 03:02 PM UTC