skip to navigation
skip to content

Planet Python

Last update: June 30, 2025 07:42 PM UTC

June 30, 2025


Zero to Mastery

[June 2025] Python Monthly Newsletter 🐍

67th issue of Andrei Neagoie's must-read monthly Python Newsletter: Fastest Python, MCP Eats The World, Optimize Your Python, and much more. Read the full newsletter to get up-to-date with everything you need to know from last month.

June 30, 2025 07:42 PM UTC


Real Python

Use TorchAudio to Prepare Audio Data for Deep Learning

Ever wondered how machine learning models process audio data? How do you handle different audio lengths, convert sound frequencies into learnable patterns, and make sure your model is robust? This tutorial will show you how to handle audio data using TorchAudio, a PyTorch-based toolkit.

You’ll work with real speech data to learn essential techniques like converting waveforms to spectrograms, standardizing audio lengths, and adding controlled noise to build machine and deep learning models.

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

  • TorchAudio processes audio data for deep learning, including tasks like loading datasets and augmenting data with noise.
  • You can load audio data in TorchAudio using the torchaudio.load() function, which returns a waveform tensor and sample rate.
  • TorchAudio normalizes audio by default during loading, scaling waveform amplitudes between -1.0 and 1.0.
  • A spectrogram visually represents the frequency spectrum of an audio signal over time, aiding in frequency analysis.
  • You can pad and trim audio in TorchAudio using torch.nn.functional.pad() and sequence slicing for uniform audio lengths.

Dive into the tutorial to explore these concepts and learn how they can be applied to prepare audio data for deep learning tasks using TorchAudio.

Take the Quiz: Test your knowledge with our interactive “Use TorchAudio to Prepare Audio Data for Deep Learning” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Use TorchAudio to Prepare Audio Data for Deep Learning

Test your grasp of audio fundamentals and working with TorchAudio in Python! You'll cover loading audio datasets, transforms, and more.

Learn Essential Technical Terms

Before diving into the technical details of audio processing with TorchAudio, take a moment to review some key terms. They’ll help you grasp the basics of working with audio data.

Waveform

A waveform is the visual representation of sound as it travels through air over time. When you speak, sing, or play music, you create vibrations that move through the air as waves. These waves can be captured and displayed as a graph showing how the sound’s pressure changes over time. Here’s an example:

A sample waveform of a 440 HZ waveA Sample Waveform of a 440 Hz Wave

This is a waveform of a 440 Hz wave, plotted over a short duration of 10 milliseconds (ms). This is called a time-domain representation, showing how the wave’s amplitude changes over time. This waveform shows the raw signal as it appears in an audio editor. The ups and downs reflect changes in loudness.

Amplitude

Amplitude is the strength or intensity of a sound wave—in other words, how loud the sound is to the listener. In the previous image, it’s represented by the height of the wave from its center line.

A higher amplitude means a louder sound, while a lower amplitude means a quieter sound. When you adjust the volume on your device, you’re actually changing the amplitude of the audio signal. In digital audio, amplitude is typically measured in decibels (dB) or as a normalized value between -1 and 1.

Frequency

Frequency is how many times a sound wave repeats itself in one second, measured in hertz (Hz). For example, a low bass note is a sound wave that repeats slowly, about 50–100 Hz. In contrast, a high-pitched whistle has a wave that repeats much faster, around 2000–3000 Hz.

In music, different frequencies create different musical notes. For instance, the A4 note that musicians use to tune their instruments is exactly 440 Hz. Now, if you were to look at the frequency plot of the 440 Hz waveform from before, here’s what you’d see:

Frequency domain plot of a 440 HZ waveA Frequency Domain Plot of a 440 Hz Wave

This plot displays the signal in the frequency domain, which shows how much of each frequency is present in the sound. The distinct peak at 440 Hz indicates that this is the dominant frequency in the signal, which is exactly what you’d expect from a pure tone. While time-domain plots—like the one you saw earlier—reveal how the sound’s amplitude changes over time, frequency-domain plots help you understand which frequencies make up the sound.

The waveform you just explored was from a 440 Hz wave. You’ll soon see that many examples in audio processing also deal with this mysterious frequency. So, what makes it so special?

Note: The 440 Hz frequency (A4 note) is the international standard pitch reference for tuning instruments. Its clear, single-frequency nature makes it great for audio tasks. These include sampling, frequency analysis, and waveform representation.

Now that you understand frequency and how it relates to sound waves, you might be wondering how computers actually capture and store these waves.

Sampling

When you record sound digitally, you’re taking snapshots of the audio wave many times per second. Each snapshot measures the wave’s amplitude at that instant. This is called sampling. The number of snapshots taken per second is the sampling rate, measured in hertz (Hz).

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


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

June 30, 2025 02:00 PM UTC

Quiz: Use TorchAudio to Prepare Audio Data for Deep Learning

In this quiz, you’ll test your understanding of audio fundamentals and how to Use TorchAudio to Prepare Audio Data for Deep Learning.

You’ll revisit fundamental terminology and how to:

Work through these questions to check your knowledge about building audio workflows for machine learning 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 ]

June 30, 2025 12:00 PM UTC


Django Weblog

Our 2024 Annual Impact Report

Django has always been more than just a web framework; it’s a testament to what a dedicated community can build together. Behind every Django release, bug fix, or DjangoCon is a diverse network of people working steadily to strengthen our open-source ecosystem. To celebrate our collective effort, the Django Software Foundation (DSF) is excited to share our 2024 Annual Impact Report 🎉

In this report, you’ll discover key milestones, narratives of community folks, the impact of the events running throughout the year, and much more, ramping up to how we’re laying the groundwork for an even more resilient and inclusive Django community.

2024 Annual Impact Report

Why we publish this report

Transparency is essential for our community-driven organization. Everyone deserves to know how our work and investments translate into real impact. It’s more than just statistics. It’s our way to:

Looking ahead: call to action

As we make progress through 2025, the Django Software Foundation remains dedicated to strengthening the ecosystem that supports developers, contributors, and users around the world. With a growing network of working groups, community initiatives, and the commitment of volunteers, we’re focused on nurturing the people and executing ideas that make Django what it is: the web framework for perfectionists with deadlines. 

Help keep this momentum strong by supporting Django through any of the following ways:

Donate to Django

Thank you, everyone, for your dedication and efforts. Here’s to another year of collaboration, contribution, and shared success!

June 30, 2025 10:00 AM UTC

June 27, 2025


Hugo van Kemenade

Run coverage on tests

I recommend running coverage on your tests.

Here’s a couple of reasons why, from the past couple of months.

Example one #

When writing tests, it’s common to copy and paste test functions, but sometimes you forget to rename the new one (see also: the Last Line Effect).

For example:

def test_get_install_to_run_with_platform(patched_installs):
 i = installs.get_install_to_run("<none>", None, "1.0-32")
 assert i["id"] == "PythonCore-1.0-32"
 assert i["executable"].match("python.exe")
 i = installs.get_install_to_run("<none>", None, "2.0-arm64")
 assert i["id"] == "PythonCore-2.0-arm64"
 assert i["executable"].match("python.exe")


def test_get_install_to_run_with_platform(patched_installs):
 i = installs.get_install_to_run("<none>", None, "1.0-32", windowed=True)
 assert i["id"] == "PythonCore-1.0-32"
 assert i["executable"].match("pythonw.exe")
 i = installs.get_install_to_run("<none>", None, "2.0-arm64", windowed=True)
 assert i["id"] == "PythonCore-2.0-arm64"
 assert i["executable"].match("pythonw.exe")

The tests pass, but the first one is never run because its name is redefined. This clearly shows up as a non-run test in the coverage report. In this case, we only need to rename one of them, and both are covered and pass.

But sometimes there’s a bug in the test which would cause it to fail, but we just don’t know because it’s not run.

Tip 1: This can also be found by Ruff’s F811 rule.
 
Tip 2: pytest’s parametrize is a great way to combine similar test functions with different input data.

Example two #

This is more subtle:

im = Image.new("RGB", (1, 1))
for colors in (("#f00",), ("#f00", "#0f0")):
 append_images = (Image.new("RGB", (1, 1), color) for color in colors)
 im_reloaded = roundtrip(im, save_all=True, append_images=append_images)

 assert_image_equal(im, im_reloaded)
 assert isinstance(im_reloaded, MpoImagePlugin.MpoImageFile)
 assert im_reloaded.mpinfo is not None
 assert im_reloaded.mpinfo[45056] == b"0100"

 for im_expected in append_images:
 im_reloaded.seek(im_reloaded.tell() + 1)
 assert_image_similar(im_reloaded, im_expected, 1)

It’s not so obvious when looking at the code, but Codecov highlights a problem:

The same code, but Codecov has flagged the last two lines were not covered

The append_images generator is being consumed inside roundtrip(), so we have nothing to iterate over in the for loop – hence no coverage. The fix is to use a list instead of a generator.


Header photo: Misplaced manhole cover (CC BY-NC-SA 2.0 Hugo van Kemenade).

June 27, 2025 05:41 PM UTC


Real Python

The Real Python Podcast – Episode #255: Structuring Python Scripts & Exciting Non-LLM Software Trends

What goes into crafting an effective Python script? How do you organize your code, manage dependencies with PEP 723, and handle command-line arguments for the best results? Christopher Trudeau is back on the show this week, bringing another batch of PyCoder's Weekly articles and projects.


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

June 27, 2025 12:00 PM UTC


Luke Plant

Statically checking Python dicts for completeness

In Python, I often have the situation where I create a dictionary, and want to ensure that it is complete – it has an entry for every valid key.

Let’s say for my (currently hypothetical) automatic squirrel-deterring water gun system, I have a number of different states the water tank can be in, defined using an enum:

from enum import StrEnum

class TankState(StrEnum):
    FULL = "FULL"
    HALF_FULL = "HALF_FULL"
    NEARLY_EMPTY = "NEARLY_EMPTY"
    EMPTY = "EMPTY"

In a separate bit of code, I define an RGB colour for each of these states, using a simple dict.

TANK_STATE_COLORS = {
    TankState.FULL: 0x00FF00,
    TankState.HALF_FULL: 0x28D728,
    TankState.NEARLY_EMPTY: 0xFF9900,
    TankState.EMPTY: 0xFF0000,
}

This is deliberately distinct from my TankState code and related definitions, because it relates to a different part of the project - the user interface. The UI concerns shouldn’t be mixed up with the core logic.

This dict is fine, and currently complete. But I’d like to ensure that if I add a new item to TankState, I don’t forget to update the TANK_STATE_COLORS dict.

With a growing ability to do static type checks in Python, some people have asked how we can ensure this using static type checks. The short answer is, we can’t (at least at the moment).

But the better question is “how can we (somehow) ensure we don’t forget?” It doesn’t have to be a static type check, as long as it’s very hard to forget, and if it preferably runs as early as possible.

Instead of shoe-horning everything into static type checks, let’s just make use of the fact that this is Python and we can write any code we want at module level. All we need to do is this:

TANK_STATE_COLORS = {
    # 

}
for val in TankState:
    assert val in TANK_STATE_COLORS, f"TANK_STATE_COLORS is missing an entry for {val}"

That’s it, that’s the whole technique. I’d argue that this is a pretty much optimal, Pythonic solution to the problem. No clever type tricks to debug later, just 2 lines of plain simple code, and it’s impossible to import your code until you fix the problem, which means you get the early checking you want. Plus you get exactly the error message you want, not some obscure compiler output, which is also really important.

It can also be extended if you want to do something more fancy (e.g. allow some values of the enum to be missing), and if it does get in your way, you can turn it off temporarily by just commenting out a couple of lines.

That’s not quite it

OK, in a project where I’m using this a lot, I did eventually get bored of this small bit of boilerplate. So, as a Pythonic extension of this Pythonic solution, I now do this:

TANK_STATE_COLORS: dict[TankState, int] = {
    TankState.FULL: 0x00FF00,
    TankState.HALF_FULL: 0x28D728,
    TankState.NEARLY_EMPTY: 0xFF9900,
    TankState.EMPTY: 0xFF0000,
}
assert_complete_enumerations_dict(TANK_STATE_COLORS)

Specifically, I’m adding:

This function needs to be “magical” because we want it to produce good error messages, like we had before. This means it needs to get hold of the name of the dict in the calling module, but functions don’t usually have access to that.

In addition, it wants to get hold of the type hint (although there would be other ways to infer it without a type hint, there are advantages this way), for which we also need the name.

The specific magic we need is:

So, because you don’t want to write all that yourself, the code is below. It also supports:

It’s got a ton of error checking, because once you get magical then you really don’t want to be debugging obscure messages.

Enjoy!

import inspect
import itertools
import sys
import typing
from collections.abc import Mapping, Sequence
from enum import Enum

from frozendict import frozendict


def assert_complete_enumerations_dict[T](the_dict: Mapping[T, object], *, allowed_missing: Sequence[T] = ()):
    """
    Magically assert that the dict in the calling module has a
    value for every item in an enumeration.
    The dict object must be bound to a name in the module.
    It must be type hinted, with the key being an Enum subclass, or Literal.
    The key may also be a tuple of Enum subclasses

    If you expect some values to be missing, pass them in `allowed_missing`
    """
    assert isinstance(the_dict, Mapping), f"{the_dict!r} is not a dict or mapping, it is a {type(the_dict)}"

    frame_up = sys._getframe(1)  # type: ignore[reportPrivateUsage]
    assert frame_up is not None
    module = inspect.getmodule(frame_up)
    assert module is not None, f"Couldn't get module for frame {frame_up}"
    msg_prefix = f"In module `{module.__name__}`,"

    module_dict = frame_up.f_locals
    name: str | None = None
    # Find the object:
    names = [k for k, val in module_dict.items() if val is the_dict]
    assert names, f"{msg_prefix} there is no name for {the_dict}, please check"

    # Any name that has a type hint will do, there will usually be one.
    hints = typing.get_type_hints(module)
    hinted_names = [name for name in names if name in hints]
    assert (
        hinted_names
    ), f"{msg_prefix} no type hints were found for {', '.join(names)}, they are needed to use assert_complete_enumerations_dict"
    name = hinted_names[0]

    hint = hints[name]
    origin = typing.get_origin(hint)
    assert origin is not None, f"{msg_prefix} type hint for {name} must supply arguments"
    assert origin in (
        dict,
        typing.Mapping,
        Mapping,
        frozendict,
    ), f"{msg_prefix} type hint for {name} must be dict/frozendict/Mapping with arguments to use assert_complete_enumerations_dict, not {origin}"

    args = typing.get_args(hint)
    assert len(args) == 2, f"{msg_prefix} type hint for {name} must have two args"

    arg0, _ = args
    arg0_origin = typing.get_origin(arg0)
    if arg0_origin is tuple:
        # tuple of Enums
        enum_list = typing.get_args(arg0)
        for enum_cls in enum_list:
            assert issubclass(
                enum_cls, Enum
            ), f"{msg_prefix} type hint must be an Enum to use assert_complete_enumerations_dict, not {enum_cls}"

        items = list(itertools.product(*(list(enum_cls) for enum_cls in enum_list)))
    elif arg0_origin is typing.Literal:
        items = typing.get_args(arg0)
    else:
        assert issubclass(
            arg0, Enum
        ), f"{msg_prefix} type hint must be an Enum to use assert_complete_enumerations_dict, not {arg0}"
        items = list(arg0)

    for item in items:
        if item in allowed_missing:
            continue

        # This is the assert we actually want to do, everything else is just error checking:
        assert item in the_dict, f"{msg_prefix} {name} needs an entry for {item}"

June 27, 2025 10:09 AM UTC


PyPodcats

Episode 9: With Tamara Atanasoska

Learn about Tamara's journey. Tamara has been contributing to open source projects since 2012. She participated in Google Summer of Code to contribute to projects like Gnome and e-cidadania.Learn about Tamara's journey. Tamara has been contributing to open source projects since 2012. She participated in Google Summer of Code to contribute to projects like Gnome and e-cidadania.

We interviewed Tamara Atanasoska.

Tamara has been contributing to open source projects since 2012. She participated in Google Summer of Code to contribute to projects like Gnome and e-cidadania.

She is now a maintainer of Fairlearn, an open-source, community-driven project to help data scientists improve fairness of AI systems.

Hear how Django helps her feel empowered, and how the PyLadies Berlin community has helped her feel welcomed as a new immigrant in Germany.

In this episode, Tamara shares perspective about open source contributions, maintain, mentorship, and her experience in running beginner-friendly sprints.

Be sure to listen to the episode to learn all about Tamara’s inspiring story!

Topic discussed

Note

This episode was recorded in March 2025. Tamara is still a software engineer, but no longer works at probabl.

To find out more about what she is currently up to, check her LinkedIn profile.

June 27, 2025 09:00 AM UTC


Django Weblog

Watch the DjangoCon Europe 2025 talks

They’re now all available to watch on YouTube, with a dedicated playlist ⭐ DjangoCon Europe 2025 Dublin. For more quality Django talks in 2025, check out our next upcoming events!

All the DjangoCon Europe talks

Welcome Session Keynote: Django needs you! (to do code review) End-to-end testing Django applications using Pytest with Playwright Turn back time: Converting integer fields to bigint using Django migrations at scale Data-Oriented Django Drei The fine print in Django release notes Django + HTMX: Patterns to Success How to solve a Python mystery Bulletproof Data Pipelines: Django, Celery, and the Power of Idempotency Logs, shells, caches and other strange words we use daily Day 1 Lightning Talks How to Enjoy Debugging in Production KEYNOTE: The Most Bizarre Software Bugs in History Passkeys in Django: the best of all possible worlds How we make decisions in Django 100 Million Parking Transactions Per Year with Django One more time about ”Django Steering Council introduction Supporting Adult Career Switchers: The Unbootcamp Method How to get Foreign Keys horribly wrong in Django Zango: Accelerating Business App Development with an Opinionated Django Meta Dynamic models without dynamic models Evolving Django: What We Learned by Integrating MongoDB Feature Flags: Deploy to some of the people all of the time, and all of the Day 2 Lightning Talks KEYNOTE: Django for Data Science: Deploying Machine Learning Models with Django The incredible Djangonaut Space project Anatomy of a Database Operation One Thousand and One Django Sites Django Admin at Scale: From Milliseconds to Microseconds 🚀 Just-in-Time Development with Django and HTMX: Faster, Leaner, and Smarter Europe, Django and two-factor authentication Closing session Day 3 Lightning Talks

June 27, 2025 06:51 AM UTC

June 25, 2025


TestDriven.io

Building a Multi-tenant App with Django

This tutorial looks at how to implement multi-tenancy in Django.

June 25, 2025 10:28 PM UTC


Peter Bengtsson

Native connection pooling in Django 5 with PostgreSQL

Enabling native connection pooling in Django 5 gives me a 5.4x speedup.

June 25, 2025 09:36 PM UTC


Real Python

Your Guide to the Python print() Function

If you’re like most Python users, then you probably started your Python journey by learning about print(). It helped you write your very own “Hello, World!” one-liner and brought your code to life on the screen. Beyond that, you can use it to format messages and even find some bugs. But if you think that’s all there is to know about Python’s print() function, then you’re missing out on a lot!

Keep reading to take full advantage of this seemingly boring and unappreciated little function. This tutorial will get you up to speed with using Python print() effectively. However, be prepared for a deep dive as you go through the sections. You may be surprised by how much print() has to offer!

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

  • The print() function can handle multiple arguments and custom separators to format output effectively.
  • You can redirect print() output to files or memory buffers using the file argument, enhancing flexibility.
  • Mocking print() in unit tests helps verify code behavior without altering the original function.
  • Using the flush argument ensures immediate output, overcoming buffering delays in certain environments.
  • Thread-safe printing is achievable by implementing locks to prevent output interleaving.

If you’re just getting started with Python, then you’ll benefit most from reading the first part of this tutorial, which illustrates the essentials of printing in Python. Otherwise, feel free to skip ahead and explore the sections that interest you the most.

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

Take the Quiz: Test your knowledge with our interactive “The Python print() Function” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

The Python print() Function

In this quiz, you'll test your understanding of Python's built-in print() function, covering how to format output, specify custom separators, and more.

Printing in a Nutshell

It’s time to jump in by looking at a few real-life examples of printing in Python. By the end of this section, you’ll know every possible way of calling print().

Producing Blank Lines

The simplest example of using Python print() requires just a few keystrokes:

Python
print()
Copied!

This produces an invisible newline character, which in turn causes a blank line to appear on your screen. To add vertical space, you can call print() multiple times in a row like this:

Python
print()
print()
print()
Copied!

It’s just as if you were hitting Enter on your keyboard in a word processor program or a text editor.

While you don’t pass any arguments to print(), you still need to put empty parentheses at the end of the line to tell Python to actually execute that function rather than just refer to it by name. Without parentheses, you’d obtain a reference to the underlying function object:

Python
>>> print()

>>> print
<built-in function print>
Copied!

The code snippet above runs within an interactive Python REPL, as indicated by the prompt (>>>). Because the REPL executes each line of Python code immediately, you see a blank line right after calling print(). On the other hand, when you skip the trailing parentheses, you get to see a string representation of the print() function itself.

As you just saw, calling print() without arguments results in a blank line, which is a line comprised solely of the newline character. Don’t confuse this with an empty string, which doesn’t contain any characters at all, not even the newline!

You can use Python’s string literals to visualize these two:

  • Blank Line: "\n"
  • Empty String: ""

The first string literal is exactly one character long, whereas the second one has no content—it’s empty.

Note: To remove the newline character from a string in Python, use its .rstrip() method, like this:

Python
>>> "A line of text.\n".rstrip()
'A line of text.'
Copied!

This strips any trailing whitespace from the right edge of the string of characters. To learn more about .rstrip(), check out the How to Strip Characters From a Python String tutorial.

Even though Python usually takes care of the newline character for you, it helps to understand how to deal with it yourself.

Dealing With Newlines

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


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

June 25, 2025 02:00 PM UTC


Mike Driscoll

An Intro to ty – The Extremely Fast Python type checker

Ty is a brand new, extremely fast Python type checker written in Rust from the fine folks at Astral, the makers of Ruff. Ty is in preview and is not ready for production use, but you can still try it out on your code base to see how it compares to Mypy or other popular Python type checkers.

Getting Started with ty

You can try out ty using the online playground, or run ty with uvx to get started quickly:

uvx ty

If you prefer to install ty, you can use pip:

python -m pip install ty

Astral provides other installation methods as well.

Using the ty Type Checker

Want to give ty a try? You can run it in much the same way as you would Ruff. Open up your terminal and navigate to your project’s top-level directory. Then run the following command:

ty check

If ty finds anything, you will quickly see the output in your terminal.

Astral has also provided a way to exclude files from type checking. By default, ty ignores files listed in an .ignore or .gitignore file.

Adding ty to Your IDE

The Astral team maintains an official VS Code extension for ty. You can get it from the VS Code Marketplace. Their documentation states that other IDEs can also use ty if they support the language server protocol.

Wrapping Up

Ruff is a great tool and has been adopted by many teams since its release. Ty will likely follow a similar trajectory if it as fast and useful as Ruff has been. Only time will tell. However, these new developments in Python tooling are exciting and will be fun to try. If you have used ty, feel free to jump into the comments and let me know what you think.

The post An Intro to ty – The Extremely Fast Python type checker appeared first on Mouse Vs Python.

June 25, 2025 12:45 PM UTC


Real Python

Quiz: The Python print() Function

In this quiz, you’ll test your understanding of Your Guide to the Python print() Function.

The print() function outputs objects to the console or a specified file-like stream. You’ll practice:

Work through these questions to reinforce your knowledge of print()’s parameters and best practices for clear, formatted I/O.


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

June 25, 2025 12:00 PM UTC


PyPodcats

Trailer: Episode 9 With Tamara Atanasoska

A preview of our chat with Tamara Atanasoska. Watch the full episode on June 27, 2025A preview of our chat with Tamara Atanasoska. Watch the full episode on June 27, 2025

Sneak Peek of our chat with Tamara Atanasoska, hosted by Georgi Ker and Mariatta Wijaya.

Tamara has been contributing to open source projects since 2012. She participated in Google Summer of Code to contribute to projects like Gnome and e-cidadania.

She is now a maintainer of Fairlearn, an open-source, community-driven project to help data scientists improve fairness of AI systems.

Hear how Django helps her feel empowered, and how the PyLadies Berlin community has helped her feel welcomed as a new immigrant in Germany.

In this episode, Tamara shares perspective about open source contributions, maintain, mentorship, and her experience in running beginner-friendly sprints.

Full episode is coming on June 27, 2025! Subscribe to our podcast now!

June 25, 2025 09:00 AM UTC


Talk Python to Me

#511: From Notebooks to Production Data Science Systems

If you're doing data science and have mostly spent your time doing exploratory or just local development, this could be the episode for you. We are joined by Catherine Nelson to discuss techniques and tools to move your data science game from local notebooks to full-on production workflows.<br/> <br/> <strong>Episode sponsors</strong><br/> <br/> <a href='https://talkpython.fm/agntcy'>Agntcy</a><br> <a href='https://talkpython.fm/sentry'>Sentry Error Monitoring, Code TALKPYTHON</a><br> <a href='https://talkpython.fm/training'>Talk Python Courses</a><br/> <br/> <h2 class="links-heading">Links from the show</h2> <div><strong>New Course: LLM Building Blocks for Python</strong>: <a href="https://training.talkpython.fm/courses/llm-building-blocks-for-python" target="_blank" >training.talkpython.fm</a><br/> <br/> <strong>Catherine Nelson LinkedIn Profile</strong>: <a href="https://www.linkedin.com/in/catherinenelson1/?featured_on=talkpython" target="_blank" >linkedin.com</a><br/> <strong>Catherine Nelson Bluesky Profile</strong>: <a href="https://bsky.app/profile/catnelson.bsky.social?featured_on=talkpython" target="_blank" >bsky.app</a><br/> <strong>Enter to win the book</strong>: <a href="https://forms.gle/1okKtSdSNTtAd4SRA?featured_on=talkpython" target="_blank" >forms.google.com</a><br/> <strong>Going From Notebooks to Scalable Systems - PyCon US 2025</strong>: <a href="https://us.pycon.org/2025/schedule/presentation/51/?featured_on=talkpython" target="_blank" >us.pycon.org</a><br/> <strong>Going From Notebooks to Scalable Systems - Catherine Nelson – YouTube</strong>: <a href="https://www.youtube.com/watch?v=o4hyA4hotxw&ab_channel=PyConUS" target="_blank" >youtube.com</a><br/> <strong>From Notebooks to Scalable Systems Code Repository</strong>: <a href="https://github.com/catherinenelson1/from_notebooks_to_scalable?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>Building Machine Learning Pipelines Book</strong>: <a href="https://www.oreilly.com/library/view/building-machine-learning/9781492053187/?featured_on=talkpython" target="_blank" >oreilly.com</a><br/> <strong>Software Engineering for Data Scientists Book</strong>: <a href="https://www.oreilly.com/library/view/software-engineering-for/9781098136192/?featured_on=talkpython" target="_blank" >oreilly.com</a><br/> <strong>Jupytext - Jupyter Notebooks as Markdown Documents</strong>: <a href="https://github.com/mwouts/jupytext?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>Jupyter nbconvert - Notebook Conversion Tool</strong>: <a href="https://github.com/jupyter/nbconvert?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>Awesome MLOps - Curated List</strong>: <a href="https://github.com/visenger/awesome-mlops?featured_on=talkpython" target="_blank" >github.com</a><br/> <strong>Watch this episode on YouTube</strong>: <a href="https://www.youtube.com/watch?v=n2WFfVIqlDw" target="_blank" >youtube.com</a><br/> <strong>Episode #511 deep-dive</strong>: <a href="https://talkpython.fm/episodes/show/511/from-notebooks-to-production-data-science-systems#takeaways-anchor" target="_blank" >talkpython.fm/511</a><br/> <strong>Episode transcripts</strong>: <a href="https://talkpython.fm/episodes/transcript/511/from-notebooks-to-production-data-science-systems" target="_blank" >talkpython.fm</a><br/> <br/> <strong>--- Stay in touch with us ---</strong><br/> <strong>Subscribe to Talk Python on YouTube</strong>: <a href="https://talkpython.fm/youtube" target="_blank" >youtube.com</a><br/> <strong>Talk Python on Bluesky</strong>: <a href="https://bsky.app/profile/talkpython.fm" target="_blank" >@talkpython.fm at bsky.app</a><br/> <strong>Talk Python on Mastodon</strong>: <a href="https://fosstodon.org/web/@talkpython" target="_blank" ><i class="fa-brands fa-mastodon"></i>talkpython</a><br/> <strong>Michael on Bluesky</strong>: <a href="https://bsky.app/profile/mkennedy.codes?featured_on=talkpython" target="_blank" >@mkennedy.codes at bsky.app</a><br/> <strong>Michael on Mastodon</strong>: <a href="https://fosstodon.org/web/@mkennedy" target="_blank" ><i class="fa-brands fa-mastodon"></i>mkennedy</a><br/></div>

June 25, 2025 08:00 AM UTC

June 24, 2025


PyCoder’s Weekly

Issue #687: Scaling With Kubernetes, Substrings, Big-O, and More (June 24, 2025)

#687 – JUNE 24, 2025
View in Browser »

The PyCoder’s Weekly Logo


Scaling Web Applications With Kubernetes and Karpenter

What goes into scaling a Python web application today? What are resources for learning and practicing DevOps skills? This week on the show, Calvin Hendryx-Parker is back to discuss the tools and infrastructure for autoscaling web applications with Kubernetes and Karpenter.
REAL PYTHON podcast

The Fastest Way to Detect a Vowel in a String

If you need to find the vowels in a string there are several different approaches you could take. This article covers 11 different ways and how each performs.
AUSTIN Z. HENLEY

Prevent Postgres Slowdowns on Python Apps with this Check List

alt

Avoid performance regressions in your Python app by staying on top of Postgres maintenance. This monthly check list outlines what to monitor, how to catch slow queries early, and ways to ensure indexes, autovacuum, and I/O are performing as expected →
PGANALYZE sponsor

O(no) You Didn’t

A deep dive into why real-world performance often defies Big-O expectations and why context and profiling matter more than theoretical complexity
MRSHINY608

PyOhio 2025 (July 26-27) Registration Open

PYOHIO.ORG

Python 3.14.0 Beta 3

CPYTHON DEV BLOG

ruff Release 0.12.0

GITHUB.COM/ASTRAL-SH

streamlit Release 1.46.0

GITHUB.COM/STREAMLIT

Discussions

Ideas: Add Virtual Threads to Python

PYTHON.ORG

Python Jobs

Sr. Software Developer (Python, Healthcare) (USA)

Prenosis

More Python Jobs >>>

Articles & Tutorials

The PSF’s 2024 Annual Impact Report Is Here!

The Python Software Foundation releases a report every year on the state of the PSF and our community. This year’s report gives a run down of the successes of the language, key highlights of PyCon US, updates from the developers in residence, and more.
PYTHON SOFTWARE FOUNDATION

Are Python Dictionaries Ordered Data Structures?

Although dictionaries have maintained insertion order since Python 3.6, they aren’t strictly speaking ordered data structures. Read on to find out why and how the edge cases can be important depending on your use case.
STEPHEN GRUPPETTA

10 Polars Tools and Techniques to Level Up Your Data Science

Are you using Polars for your data science work? There are many libraries out there that might help you write less code. Talk Python interviews Christopher Trudeau and they talk about the Polars ecosystem.
KENNEDY & TRUDEAU podcast

Cut Django DB Latency With Native Connection Pooling

“Deploy Django 5.1’s native connection pooling in 10 minutes to cut database latency by 50-70ms, reduce connection overhead by 60-80%, and improve response times by 10-30% with zero external dependencies.”
SAURABH KUMAR

Will AI Replace Junior Developers?

At PyCon US this year, Adarsh chatted with various Python folks about one big question: will AI replace junior developers? He spoke with Guido van Rossum, Anthony Shaw, Simon Willison, and others.
ADARSH DIVAKARAN ‱ Shared by Adarsh Divakaran

PEP 779: Free-Threaded Python (Accepted)

Free-threaded Python has been upgraded from experimental to part of the supported build. This quick quote from a longer discussion covers exactly what that means.
SIMON WILSON

PSF Board Election Schedule

It is time for the Python Software Foundation Board elections. Nominations are due by July 29th. See the article for the full election schedule and deadlines.
PYTHON SOFTWARE FOUNDATION

Exploring Python’s list Data Type With Examples

In this video course, you’ll dive deep into Python’s lists: how to create them, update their content, populate and grow them - with practical code examples.
REAL PYTHON course

Write Pythonic and Clean Code With namedtuple

Discover how Python’s namedtuple lets you create simple, readable data structures with named fields you can access using dot notation.
REAL PYTHON

Execute Your Python Scripts With a Shebang

In this video course, you’ll learn when and how to use the shebang line in your Python scripts to execute them from a Unix-like shell.
REAL PYTHON course

All About the TypedDict

Are you fan of type hinting in Python? Learn how to add typing to a dictionary with different types of keys.
MIKE DRISCOLL

Projects & Code

smartypants.py: Plain ASCII to “Smart” Punctuation

GITHUB.COM/JUSTINMAYER

nbdev: Create Delightful Software With Jupyter Notebooks

GITHUB.COM/ANSWERDOTAI

tournaments: Web-Based Tournament Management

GITHUB.COM/KOSMOTIVE

bulletchess: High Performance Python Chess

GITHUB.COM/ZEDECKJ

pexpect: Control Interactive Programs in a Pseudo-Terminal

GITHUB.COM/PEXPECT

Events

Weekly Real Python Office Hours Q&A (Virtual)

June 25, 2025
REALPYTHON.COM

PyCamp Leipzig 2025

June 28 to June 30, 2025
BARCAMPS.EU

Launching Python Katsina Community

June 28 to June 29, 2025
PYTHONKATSINA.ORG

PyDelhi User Group Meetup

June 28, 2025
MEETUP.COM

Workshop: Creating Python Communities

June 29 to June 30, 2025
PYTHON-GM.ORG

PyCon Colombia 2025

July 4 to July 7, 2025
PYCON.CO


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

alt

[ Subscribe to 🐍 PyCoder’s Weekly 💌 – Get the best Python news, articles, and tutorials delivered to your inbox once a week >> Click here to learn more ]

June 24, 2025 07:30 PM UTC


Real Python

Starting With DuckDB and Python

The DuckDB database provides a seamless way to handle large datasets in Python with Online Analytical Processing (OLAP) optimization. You can create databases, verify data imports, and perform efficient data queries using both SQL and DuckDB’s Python API.

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 ]

June 24, 2025 02:00 PM UTC

June 23, 2025


Real Python

Python enumerate(): Simplify Loops That Need Counters

Python’s enumerate() function helps you with loops that require a counter by adding an index to each item in an iterable. This is particularly useful when you need both the index and value while iterating, such as listing items with their positions. You can also customize the starting index with the start argument, offering flexibility in various scenarios.

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

  • enumerate() in Python adds a counter to an iterable and returns it as an enumerate object, pairing each item with an index.
  • enumerate() accepts an iterable and an optional start argument to set the initial index value.
  • The advantage of enumerate() is that it provides both index and value pairs without manual counter management.
  • You can use zip() or slicing as alternatives to enumerate() for iterating multiple sequences or selecting specific elements.

Explore how to implement your own version of enumerate() and discover alternative methods like zip() and itertools for more complex iteration patterns.

Get Your Code: Click here to download the free sample code you’ll use to explore how enumerate() works in Python.

Using Python’s enumerate()

There are situations when you need both the index and the value of items in an iterable. That’s when Python’s enumerate() function can come in handy for you.

Python’s enumerate() function adds a counter to an iterable and returns it in the form of an enumerate object, which can be used directly in loops. For example, when you want to display the winners of a race, you might write:

Python
>>> runners = ["Lenka", "Martina", "Gugu"]
>>> for winner in enumerate(runners):
...     print(winner)
...
(0, 'Lenka')
(1, 'Martina')
(2, 'Gugu')
Copied!

Since enumerate() is a built-in function, you can use it right away without importing it. When you use enumerate() in a for loop, you get pairs of count and value from the iterable.

Note: If you’re coming from languages like C, Java, or JavaScript, you might be tempted to use range(len()) to get both the index and value in a loop. While this works in Python, enumerate() is considered a more Pythonic and preferred approach.

In the example above, you’re storing the position and the runner’s name in a variable named winner, which is a tuple. To display the position and the name right away, you can unpack the tuple when you define the for loop:

Python
>>> runners = ["Lenka", "Martina", "Gugu"]
>>> for position, name in enumerate(runners):
...     print(position, name)
...
0 Lenka
1 Martina
2 Gugu
Copied!

Just like the winner variable earlier, you can name the unpacked loop variables whatever you want. You use position and name in this example, but they could just as easily be named i and value, or any other valid Python names.

When you use enumerate() in a for loop, you typically tell Python to use two variables: one for the count and one for the value itself. You’re able to do this by applying a Python concept called tuple unpacking.

Unpacking is the idea that a tuple—or another type of a Python sequence—can be split into several variables depending on the length of that sequence. For instance, you can unpack a tuple of two elements into two variables:

Python
>>> cart_item = ("Wireless Mouse", 2)
>>> product_name, quantity_ordered = cart_item
>>> product_name
'Wireless Mouse'
>>> quantity_ordered
2
Copied!

First, you create a tuple with two elements, "Wireless Mouse" and 2. Then, you unpack that tuple into product_name and quantity_ordered, which are each assigned one of the values from the tuple.

When you call enumerate() and pass a sequence of values, Python returns an iterator. When you ask the iterator for its next value, it yields a tuple with two elements. The first element of the tuple is the count, and the second element is the value from the sequence that you passed:

Python
>>> values = ["first", "second"]

>>> enumerate_instance = enumerate(values)
>>> print(enumerate_instance)
<enumerate at 0x7fe75d728180>

>>> next(enumerate_instance)
(0, 'first')

>>> next(enumerate_instance)
(1, 'second')

>>> next(enumerate_instance)
Traceback (most recent call last):
  File "<python-input-5>", line 1, in <module>
    next(enumerate_instance)
    ~~~~^^^^^^^^^^^^^^^
StopIteration
Copied!

In this example, you create a Python list called values with two elements, "first" and "second". Then, you pass values to enumerate() and assign the return value to enumerate_instance. When you print enumerate_instance, you’ll see that it’s an enumerate object with a particular memory address.

Then, you use Python’s built-in next() to get the next value from enumerate_instance. The first value that enumerate_instance returns is a tuple with the count 0 and the first element from values, which is "first".

Calling next() again on enumerate_instance yields another tuple—this time, with the count 1 and the second element from values, "second". Finally, calling next() one more time raises a StopIteration exception since there are no more values to be returned from enumerate_instance.

When an iterable is used in a for loop, Python automatically calls next() at the start of every iteration until StopIteration is raised. Python assigns the value it retrieves from the iterable to the loop variable.

By default, the count of enumerate() starts at 0. This isn’t ideal when you want to display the winners of a race. Luckily, Python’s enumerate() has one additional argument that you can use to control the starting value of the count.

When you call enumerate(), you can use the start argument to change the starting count:

Python
>>> runners = ["Lenka", "Martina", "Gugu"]
>>> for position, name in enumerate(runners, start=1):
...     print(position, name)
...
1 Lenka
2 Martina
3 Gugu
Copied!

In this example, you pass start=1, which initializes position with the value 1 on the first loop iteration.

You should use enumerate() anytime you need to use the count and an item in a loop. Keep in mind that enumerate() increments the count by one on every iteration. However, this only slightly limits your flexibility. Since the count is a standard Python integer, you can use it in many ways.

Practicing With Python enumerate()

Now that you’ve explored the basics of enumerate(), it’s time to practice using enumerate() with some real-world examples.

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


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

June 23, 2025 02:00 PM UTC


Daniel Roy Greenfeld

TIL: HTML 404 errors for FastAPI

I had a TIL about custom responses in FastAPI but there's enough nuance that it deserves a full blog post. In the meantime, here's a TIL about custom HTTP responses.

from fastapi import FastAPI
from fastapi.responses import HTMLResponse


async def custom_404_exception_handler(request, exc):
    return HTMLResponse(
        f'<p>404 Not Found at "{request.url.path}"</p>', status_code=404
    )

# Add more HTTP exceptions as needed
HTTP_EXCEPTIONS = {404: custom_404_exception_handler}

app = FastAPI(exception_handlers=HTTP_EXCEPTIONS)


@app.get("/")
async def read_root():
    return {"Hello": "World"}

Try it out by running the app and going to a non-existent path, like /not-found. You should see a simple HTML page with a 404 message.

June 23, 2025 01:00 PM UTC


Python Bytes

#437 Python Language Summit 2025 Highlights

<strong>Topics covered in this episode:</strong><br> <ul> <li><em>* <a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025.html?featured_on=pythonbytes">The Python Language Summit 2025</a></em>*</li> <li><strong><a href="https://willmcgugan.github.io/fixing-python-properties/?featured_on=pythonbytes">Fixing Python Properties</a></strong></li> <li><em>* <a href="https://github.com/rohaquinlop/complexipy?featured_on=pythonbytes">complexipy</a></em>*</li> <li><em>* <a href="https://github.com/OKUA1/juvio?featured_on=pythonbytes">juvio</a></em>*</li> <li><strong>Extras</strong></li> <li><strong>Joke</strong></li> </ul><a href='https://www.youtube.com/watch?v=sOJf3iBM6Tg' style='font-weight: bold;'data-umami-event="Livestream-Past" data-umami-event-episode="437">Watch on YouTube</a><br> <p><strong>About the show</strong></p> <p><strong>Sponsored by Posit:</strong> <a href="https://pythonbytes.fm/connect">pythonbytes.fm/connect</a></p> <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>Michael #1: <a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025.html?featured_on=pythonbytes">The Python Language Summit 2025</a></strong></p> <ul> <li>Write up by Seth Michael Larson</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-how-can-we-make-breaking-changes-less-painful.html?featured_on=pythonbytes">How can we make breaking changes less painful?</a>: talk by Itamar Oren</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-uncontentious-talk-about-contention.html?featured_on=pythonbytes">An Uncontentious Talk about Contention</a>: talk by Mark Shannon</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-state-of-free-threaded-python.html?featured_on=pythonbytes">State of Free-Threaded Python</a>: talk by Matt Page</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-fearless-concurrency.html?featured_on=pythonbytes">Fearless Concurrency</a>: talk by Matthew Parkinson, Tobias Wrigstad, and Fridtjof Stoldt</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-challenges-of-the-steering-council.html?featured_on=pythonbytes">Challenges of the Steering Council</a>: talk by Eric Snow</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-docs-editorial-board.html?featured_on=pythonbytes">Updates from the Python Docs Editorial Board</a>: talk by Mariatta</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-packaging-governance-process.html?featured_on=pythonbytes">PEP 772 - Packaging Governance Process</a>: talk by Barry Warsaw and Pradyun Gedam</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-python-on-mobile.html?featured_on=pythonbytes">Python on Mobile - Next Steps</a>: talk by Russell Keith-Magee</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-what-do-core-developers-want-from-rust.html?featured_on=pythonbytes">What do Python core developers want from Rust?</a>: talk by David Hewitt</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-upstreaming-the-pyodide-js-ffi.html?featured_on=pythonbytes">Upstreaming the Pyodide JS FFI</a>: talk by Hood Chatham</li> <li><a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-lightning-talks.html?featured_on=pythonbytes">Lightning Talks</a>: talks by Martin DeMello, Mark Shannon, Noah Kim, Gregory Smith, Guido van Rossum, Pablo Galindo Salgado, and Lysandros Nikolaou</li> </ul> <p><strong>Brian #2:</strong> <a href="https://willmcgugan.github.io/fixing-python-properties/?featured_on=pythonbytes">Fixing Python Properties</a></p> <ul> <li>Will McGugan</li> <li>“Python properties work well with type checkers such Mypy and friends. 
 The type of your property is taken from the getter only. Even if your setter accepts different types, the type checker will complain on assignment.”</li> <li>Will describes a way to get around this and make type checkers happy.</li> <li>He replaces <code>@property</code> with a descriptor. It’s a cool technique.</li> <li>I also like the way Will is allowing different ways to use a property such that it’s more convenient for the user. This is a cool deverloper usability trick.</li> </ul> <p><strong>Brian #3: <a href="https://github.com/rohaquinlop/complexipy?featured_on=pythonbytes">complexipy</a></strong></p> <ul> <li>Calculates the cognitive complexity of Python files, written in Rust.</li> <li>Based on the cognitive complexity measurement described in a white paper by Sonar</li> <li>Cognitive complexity builds on the idea of cyclomatic complexity.</li> <li>Cyclomatic complexity was intended to measure the “testability and maintainability” of the control flow of a module. Sonar argues that it’s fine for testability, but doesn’t do well with measuring the “maintainability” part. So they came up with a new measure.</li> <li>Cognitive complexity is intended to reflects the relative difficulty of understanding, and therefore of maintaining methods, classes, and applications.</li> <li>complexipy essentially does that, but also has a really nice color output.</li> <li>Note: at the very least, you should be using “cyclomatic complexity” <ul> <li>try with <code>ruff check --select C901</code></li> </ul></li> <li>But also try complexipy.</li> <li>Great for understanding which functions might be ripe for refactoring, adding more documentation, surrounding with more tests, etc.</li> </ul> <p><strong>Michael #4: <a href="https://github.com/OKUA1/juvio?featured_on=pythonbytes">juvio</a></strong></p> <ul> <li>uv kernel for Jupyter</li> <li>⚙ <strong>Automatic Environment Setup:</strong> When the notebook is opened, Juvio installs the dependencies automatically in an ephemeral virtual environment (using <code>uv</code>), ensuring that the notebook runs with the correct versions of the packages and Python</li> <li>📁 <strong>Git-Friendly Format:</strong> Notebooks are converted on the fly to a script-style format using <code># %%</code> markers, making diffs and version control painless</li> <li>Why Use Juvio? <ul> <li>No additional lock or requirements files are needed</li> <li>Guaranteed reproducibility</li> <li>Cleaner Git diffs</li> </ul></li> <li>Powered By <ul> <li><code>uv</code> – ultra-fast Python package management</li> <li><code>PEP 723</code> – Python inline dependency standards</li> </ul></li> </ul> <p><strong>Extras</strong></p> <p>Brian:</p> <ul> <li><a href="https://testandcode.com?featured_on=pythonbytes">Test &amp; Code</a> in slow mode currently. But will be back with some awesome interviews.</li> </ul> <p><strong>Joke: <a href="https://www.youtube.com/watch?v=hwG89HH0VcM">The 0.1x Engineer</a></strong></p> <ul> <li>via BalĂĄzs</li> <li>Also <ul> <li><a href="https://www.youtube.com/watch?v=NY2nnsAplSo&ab_channel=StormtrooperVlogs">StormTrooper vlog</a></li> <li><a href="https://www.youtube.com/watch?v=oHYaOdIyuQA">BIGFOOT VLOG - ATTACKED BY WENDIGO!</a></li> </ul></li> </ul>

June 23, 2025 08:00 AM UTC

June 21, 2025


Will McGugan

Seeking sponsorship for Rich and Textual

After a somewhat stressful three years running a startup, I am takings a year's sabbatical. I'm going to use this time to focus on my health‐something I have neglected. As good as it feels not to work full-time, I still plan on maintaining Rich, Textual and other Open Source projects, in addition to offering free tech support.

Since I don't have any income at the moment, I want to start looking for sponsorship again. I'm hoping it will rise to a level where it will cover living costs for the year, but I'll be happy if it pays for coffee.

If you have benefited from my work in the past, consider sponsoring me. Whatever you feel comfortable with.

If your organization has extracted any value from my work, then consider picking one of the higher tiers to return the favor. I may be able to assist you with your project, wether it is terminal related or not. There is a lot of knowledge in my fleshy mammalian brain. Even in the age of AI, it could still benefit you.

June 21, 2025 04:50 PM UTC