skip to navigation
skip to content

Planet Python

Last update: January 22, 2025 01:42 AM UTC

January 21, 2025


PyCoder’s Weekly

Issue #665: Dict Comprehensions, Data Visualization, Memory Leaks, and More (Jan. 21, 2025)

#665 – JANUARY 21, 2025
View in Browser »

The PyCoder’s Weekly Logo


Building Dictionary Comprehensions in Python

In this video course, you’ll learn how to write dictionary comprehensions in Python. You’ll also explore the most common use cases for dictionary comprehensions and learn about some bad practices that you should avoid when using them in your code.
REAL PYTHON course

PyViz: Python Tools for Data Visualization

This site contains an overview of all the different visualization libraries in the Python ecosystem. If you’re trying to pick a tool, this is a great place to better understand the pros and cons of each.
PYVIZ.ORG

Building AI Agents With Your Enterprise Data: A Developer’s Guide

alt

Building AI agents over enterprise data is hard—legacy systems, scattered data, complex queries. MindsDB, a leading open-source enterprise AI platform, makes it much easier: turn your data into AI-driven ‘skills’ and build smarter, more customized agents →
MINDSDB sponsor

Catching Memory Leaks With Your Test Suite

“If you have a good test suite, you may be able to use pytest fixtures to identify memory and other resource leaks.”
ITAMAR TURNER-TRAURING

Djangonaut Space Session 4 Applications Open

DJANGONAUT.SPACE

Python 3.14.0 Alpha 4 Released

PYTHON.ORG

Django 5.2 Alpha 1 Released

DJANGO SOFTWARE FOUNDATION

Django Security Releases Issued: 5.1.5, 5.0.11, and 4.2.18

DJANGO SOFTWARE FOUNDATION

EuroPython Prague 2025 Call for Proposals

EUROPYTHON.EU

Python Jobs

Backend Software Engineer (Anywhere)

Brilliant.org

More Python Jobs >>>

Articles & Tutorials

10 Ways to Work With Large Files in Python

“Handling large text files in Python can feel overwhelming. When files grow into gigabytes, attempting to load them into memory all at once can crash your program.” This article covers different ways of dealing with this challenge.
ALEKSEI ALEINIKOV

Investigating the Popularity of Python Build Backends

This post analyzes the popularity of build backends used in pyproject.toml files over time. Over half of the projects analyzed use setuptools, with Poetry coming in second around 30%.
BASTIAN VENTHUR

Testing Your Python Package Releases

Upon creating the release for the Django Debug Toolbar, Tim discovered a problem when uploading to PyPI. This article talks about how he could have caught it earlier with better tests.
TIM SCHILLING

How I Automated Data Cleaning in Python

Learn how to automate data cleaning in Python using reusable functions and pipelines. Improve efficiency by handling missing values, duplicates, and data types.
SATYAM SAHU

The “Active Enum” Pattern

This article talks about the challenges associated with enum declarations being separate from their associated business logic, and proposes some alternatives.
GLYPH LEFKOWITZ

A Guide to JAX for PyTorch Developers

“PyTorch users can learn about JAX in this tutorial that connects JAX concepts to the PyTorch building blocks that they’re already familiar with.”
ANFAL SIDDIQUI

Use a Python venv in a Container Like Docker

Bite code talks about why you should use a virtual environment inside of Docker containers, even though that is containment within a container.
BITE CODE!

Creating a Fitness Tracker App With Python Reflex

A detailed guide to building a simple Fitness Tracker app in Python using Reflex that lets you log the number of workouts completed per week.
BOB BELDERBOS • Shared by Bob Belderbos

Database Indexing in Django

This article explores the basics of database indexing, its advantages and disadvantages, and how to apply it in a Django application.
OLUWOLE MAJIYAGBE • Shared by Michael Herman

Python’s range() Function

The range() function can be used for counting upward, countdown downward, or performing an operation a number of times.
TREY HUNNER

Quickly Visualizing an SBOM Document

Quick instructions on how to chart a Software Bill-Of-Materials (SBOM) document.
SETH LARSON

Projects & Code

Zasper: A Supercharged IDE for Data Science

N/A
ZASPER.IO • Shared by Poruri Sai Rahul

pyper: Concurrent Python Made Simple

GITHUB.COM/PYPER-DEV

freezegun: Mocks the datetime Module for Testing

GITHUB.COM/SPULEC

guppy3: Guppy/Heapy Ported to Python3

GITHUB.COM/ZHUYIFEI1999

VocabCLI: Word Insights TUI

GITHUB.COM/HIGHNESSATHARVA • Shared by Atharva Shah

Events

Weekly Real Python Office Hours Q&A (Virtual)

January 22, 2025
REALPYTHON.COM

PyCon+Web 2025

January 24 to January 26, 2025
PYCONWEB.COM

PyDelhi User Group Meetup

January 25, 2025
MEETUP.COM

PythOnRio Meetup

January 25, 2025
PYTHON.ORG.BR

Python Leiden User Group

January 27, 2025
MEETUP.COM

Python Sheffield

January 28, 2025
GOOGLE.COM


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

January 21, 2025 07:30 PM UTC


"Mathspp Pydon'ts"

Decorators | Pydon't 🐍

This article teaches the decorator pattern in Python, why it exists, how to use it, and when to use it to write efficient and idiomatic Python code.

Decorators

The decorator pattern is a functional pattern that Python developers leverage to write more modular and composable functions. In this Pydon't, you will learn exactly why the decorator pattern matters, how to use it, and when to use it. You will also learn how to implement your custom decorators and more advanced use cases of decorators.

In this Pydon't, you will:

A function that did too much

The decorator pattern is a pattern that lets you complement a function with behaviour that is useful but that is orthogonal to the original objective of the function. This pattern is relevant because you do not want to overcrowd your functions, and at the same time it allows you to define this useful behaviour in a way that is reusable by other functions.

As an example, consider how you might have implemented the mathematical operation factorial before it was introduced in the module math:

# In modern Python: from math import factorial
def factorial(n):
    r = 1
    while n > 1:
        r *= n
        n -= 1
    return r

If you are calling this function a lot with a few large integers as arguments, you may want to cache the results you compute. For this effect, you may want to use a dictionary that maps inputs to outputs:

_factorial_cache = {}

def factorial(n):
    if n not in _factorial_cache:
        _n = n
        r = 1
        while _n > 1:
            r *= _n
            _n -= 1
        _factorial_cache[n] = r

    return _factorial_cache[n]

This solution is far from ideal, since you introduced a function cache that is only loosely coupled to the function it's relevant for, while also introducing code in the function that is not really relevant for the original objective of the function.

Instead of baking caching into the function, which is a poor one-time solution for something I might want to do with several functions, I can write a higher-order function that adds caching to any function I want. Let me walk you through this transformation.

Factoring out the orthogonal behaviour

Instead of...

January 21, 2025 05:11 PM UTC


Real Python

Exploring Python's tuple Data Type With Examples

In Python, a tuple is a built-in data type that allows you to create immutable sequences of values. The values or items in a tuple can be of any type. This makes tuples pretty useful in those situations where you need to store heterogeneous data, like that in a database record, for example.

Through this tutorial, you’ll dive deep into Python tuples and get a solid understanding of their key features and use cases. This knowledge will allow you to write more efficient and reliable code by taking advantage of tuples.

In this video course, you’ll learn how to:


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

January 21, 2025 02:00 PM UTC


Malthe Borch

Keeping tabs on migration processes

To manage migration processes such as adopting a new data integration tool or rehosting applications at scale from one infrastructure service to another, organizations often turn away from established work planning and management tools such as Azure DevOps Boards.

Instead, project managers often develop their own systems based on the trusted spreadsheet, typically Microsoft Excel. While these spreadsheets may be shared with the development team, this approach significantly reduces transparency and results in information redundancy. In addition, the benefits of using an existing tool are lost, perhaps most importantly reporting. When all you have is a hammer, and all that.

Alternatively, existing work items such as user stories and tasks are used to model the migration process, which is an impedance mismatch because "Migrate application X" makes for a terrible user story, tasks must be cloned for each story, the setup is time-consuming and error-prone, and the user interface becomes cluttered due to repetition. When all you have is a hammer, and all that.

A better approach is to introduce a new business process, tailored to the task at hand.

Any half-decent work management system will support this sort of tailoring. For example, with Azure DevOps, we can add a custom work item type to represent this business process, and with Jira you can create a new workflow.

An example from Azure DevOps, where I have defined a number of new states for the "in progress" category to model a rehosting migration process:

In Azure DevOps, the states and transition rules (for example to restrict transition to a specific state) can be adapted during the project's lifetime, if new requirements emerge. You can add a new portfolio backlog to manage the custom work item type on a separate kanban board.

Using this approach, you reap the full benefits of using a dedicated work management tool and we can let the system take care of reporting rather than having to dedicate a significant portion of time for what's essentially a menial task.

January 21, 2025 01:40 PM UTC


Python Bytes

#417 Bugs hide from the light

<strong>Topics covered in this episode:</strong><br> <ul> <li><strong><a href="https://github.com/d4v3y0rk/llm_catcher?featured_on=pythonbytes">LLM Catcher</a></strong></li> <li><strong>On PyPI Quarantine process</strong></li> <li><strong><a href="https://github.com/lundberg/respx?featured_on=pythonbytes">RESPX</a></strong></li> <li><strong><a href="https://mathspp.com/blog/til/unpacking-kwargs-with-custom-objects?featured_on=pythonbytes">Unpacking kwargs with custom objects</a></strong></li> <li><strong>Extras</strong></li> <li><strong>Joke</strong></li> </ul><a href='https://www.youtube.com/watch?v=HS1rMTdq4Ko' style='font-weight: bold;'data-umami-event="Livestream-Past" data-umami-event-episode="417">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"><strong>@mkennedy@fosstodon.org</strong></a> <strong>/</strong> <a href="https://bsky.app/profile/mkennedy.codes?featured_on=pythonbytes"><strong>@mkennedy.codes</strong></a> <strong>(bsky)</strong></li> <li>Brian: <a href="https://fosstodon.org/@brianokken"><strong>@brianokken@fosstodon.org</strong></a> <strong>/</strong> <a href="https://bsky.app/profile/brianokken.bsky.social?featured_on=pythonbytes"><strong>@brianokken.bsky.social</strong></a></li> <li>Show: <a href="https://fosstodon.org/@pythonbytes"><strong>@pythonbytes@fosstodon.org</strong></a> <strong>/</strong> <a href="https://bsky.app/profile/pythonbytes.fm"><strong>@pythonbytes.fm</strong></a> <strong>(bsky)</strong></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:</strong> <a href="https://github.com/d4v3y0rk/llm_catcher?featured_on=pythonbytes">LLM Catcher</a></p> <ul> <li>via Pat Decker</li> <li>Large language model diagnostics for python applications and FastAPI applications .</li> <li>Features <ul> <li>Exception diagnosis using LLMs (Ollama or OpenAI)</li> <li>Support for local LLMs through Ollama</li> <li>OpenAI integration for cloud-based models</li> <li>Multiple error handling approaches: <ul> <li>Function decorators for automatic diagnosis</li> <li>Try/except blocks for manual control</li> <li>Global exception handler for unhandled errors from imported modules</li> </ul></li> <li>Both synchronous and asynchronous APIs</li> <li>Flexible configuration through environment variables or config file</li> </ul></li> </ul> <p><strong>Brian #2:</strong> On PyPI Quarantine process</p> <ul> <li>Mike Fiedler</li> <li><a href="https://blog.pypi.org/posts/2024-08-16-safety-and-security-engineer-year-in-review/#project-lifecycle-status-quarantine">Project Lifecycle Status - Quarantine</a> in his "Safety &amp; Security Engineer: First Year in Review post” </li> <li>Some more info now in <a href="https://blog.pypi.org/posts/2024-12-30-quarantine/?featured_on=pythonbytes">Project Quarantine</a></li> <li>Reports of malware in a project kick things off</li> <li>Admins can now place a project in quarantine, allowing it to be unavailable for install, but still around for analysis.</li> <li>New process allows for packages to go back to normal if the report is false.</li> <li>However <ul> <li>Since August, the Quarantine feature has been in use, with PyPI Admins marking ~140 reported projects as Quarantined.</li> <li>Of these, <strong>only a single project</strong> has exited Quarantine, others have been removed.</li> </ul></li> </ul> <p><strong>Michael #3:</strong> <a href="https://github.com/lundberg/respx?featured_on=pythonbytes">RESPX</a></p> <ul> <li>Mock HTTPX with awesome request patterns and response side effects <img src="https://paper.dropboxstatic.com/static/img/ace/emoji/1f98b.png?version=8.0.0" alt="butterfly" /></li> <li>A simple, <em>yet powerful</em>, utility for mocking out the <a href="https://www.python-httpx.org/?featured_on=pythonbytes">HTTPX</a>, <em>and</em> <a href="https://www.encode.io/httpcore/?featured_on=pythonbytes"><em>HTTP Core</em></a>, libraries.</li> <li>Start by <a href="https://lundberg.github.io/respx/guide/#mock-httpx">patching</a> HTTPX, using respx.mock, then add request <a href="https://lundberg.github.io/respx/guide/#routing-requests">routes</a> to mock <a href="https://lundberg.github.io/respx/guide/#mocking-responses">responses</a>.</li> <li>For a neater pytest experience, RESPX includes a respx_mock <em>fixture</em></li> </ul> <p><strong>Brian #4:</strong> <a href="https://mathspp.com/blog/til/unpacking-kwargs-with-custom-objects?featured_on=pythonbytes">Unpacking kwargs with custom objects</a></p> <ul> <li>Rodrigo</li> <li>A class needs to have <ul> <li>a keys() method that returns an iterable.</li> <li>a __getitem__() method for lookup</li> </ul></li> <li>Then double splat ** works on objects of that type.</li> </ul> <p><strong>Extras</strong> </p> <p>Brian:</p> <ul> <li><a href="https://hugovk.dev/blog/2024/a-surprising-thing-about-pypis-bigquery-data?featured_on=pythonbytes">A surprising thing about PyPI's BigQuery data</a> - Hugovk <ul> <li><a href="https://hugovk.github.io/top-pypi-packages/?featured_on=pythonbytes">Top PyPI Packages</a><a href="https://hugovk.github.io/top-pypi-packages/?featured_on=pythonbytes"> </a>(and therefore also <a href="https://pythontest.com/top-pytest-plugins/?featured_on=pythonbytes">Top pytest Plugins</a>) uses a BigQuery dataset</li> <li>Has grabbed 30-day data of 4,000, then 5,000, then 8,000 packages.</li> <li>Turns out 531,022 packages (amount returned when limit set to a million) is the same cost.</li> <li>So…. hoping future updates to these “Top …” pages will have way more data. </li> </ul></li> <li>Also, was planning on recording a <a href="https://testandcode.com?featured_on=pythonbytes">Test &amp; Code</a> episode on pytest-cov today, but haven’t yet. Hopefully at least a couple of new episodes this week.</li> <li>Finally updated <a href="https://pythontest.com?featured_on=pythonbytes">pythontest.com</a> with BlueSky links on home page and contact page.</li> </ul> <p>Michael:</p> <ul> <li>Follow up from Owen (<a href="https://github.com/owenlamont/uv-secure?featured_on=pythonbytes">uv-secure</a>): <ul> <li>Thanks for the multiple shout outs! uv-secure just uses the PyPi json API at present to query package vulnerabilities (same as default source for pip audit). I do smash it asynchronously for all dependencies at once... but it still takes a few seconds.</li> </ul></li> </ul> <p><strong>Joke:</strong> <a href="https://www.codepuns.com/post/770746548202127360/why-do-programmers-prefer-dark-mode?featured_on=pythonbytes">Bugs hide from the light</a>!</p>

January 21, 2025 08:00 AM UTC


Fabio Zadrozny

Using (or really misusing) Path.resolve() in Python

 

I just stumbled upon a code in Python that uses a simple `Path(...).resolve()` after receiving a path in an API and suddenly reminded myself on the many the bugs I've tripped over due to it, so, decided to share  why I hope at some point this function stops being so pervasive as it's usually the wrong thing to call.. (maybe because when Python went from os.path to pathlib they added no real replacement and now you need to use both).

The main reason of bugs for that is that when you call Path.resolve() it'll actually resolve symlinks (and substs on Windows).

This means that if the user crafted some structure as

/myproject

/myproject/package.json

/myproject/src -> symlink to sources in /allmysources/temp

 If you resolve `/myproject/src/myfile.py` to `/allmysources/temp/myfile.py` and actually want to get to the `package.json`, it'll never be found!

 I was even looking at the python docs and found this nugget when talking about `Path.parent`:

If you want to walk an arbitrary filesystem path upwards, it is recommended to first call Path.resolve() so as to resolve symlinks and eliminate ".." components.

And that's completely why you shouldn't use it because if you do, then the parents will be completely off!

So, what should you do?

Unfortunately pathlib is not your friend here, you need to use `os.path.normpath(os.path.abspath(...))` to remove `..` occurrences from the string and make it absolute (and then after, sure, use pathlib for the remainder of your program) -- possibly you even want to get the real case in the filesystem if you're on Windows (which is very annoying as then you end up needing to do a bunch of listdir() calls to get the case stored in the filesystem).

 -- but also, keep in mind you usually just need to do that on boundaries (i.e.: when you receive a relative path as an argument in the command line for instance, not when you receive an API call from another program -- chances are, the cwd of that program and your own are different and thus calls to `absolute()` or `resolve()` are actually bugs).

But isn't there any use-case for `Path.resolve()`?

As far as I know, the only case where it's valid is if you do want to create a cache of sorts where any representation of that file is considered the same (i.e.: you really want the canonical representation of the file). 

Say, in an IDE you opened your `subst` in `x:` and then you have `c:\project\foo.py` and `x:\foo.py` in a debugger and you want to always show the version that's opened under your IDE, you need to build that mapping so that regardless of the version that's accessed you will open the version that's being seen in your IDE (and oh my god, I've seen so many IDEs get that wrong and the effect is usually you'll have the same file opened under different names in the IDE -- I know that in the pydevd debugger this is especially tricky because the name of the file is gotten from a .pyc file, which depends on how it was generated and the cached version may not match the version that the user is currently seeing -- the  debugger goes through great lengths to have an internal canonical representation and a different version which should be what the user sees, but it's not perfect and IDEs which actually open the file afterwards don't make the due diligence to try to do the proper mapping afterwards -- even worse when they fail because the path is the same but the drive is uppercase and internally the path they have has the drive in lowercase).

Maybe even then it'd be better to use the inode of the file for a reference (gotten from `Path.stat()`)...

Anyways, to sum up, in its current format, I'd just recommend to ALMOST NEVER use `resolve()` as it's usually just the source of bugs, keep to `Path(os.path.normpath(os.path.abspath(...)))` on program boundaries as that's just saner in general (and when you want to pass files among APIs, make sure paths are already absolute and normalized and fail if they aren't).

p.s.: just as a disclaimer, I've also seen a very minor subset of users on Linux (just one so far really, but maybe there are others that want that behavior out there) that say they want the symlinks resolved as the created structure they have is always final and the symlinks are just a commodity to avoid having to cd into that structure so that they can freely cd into symlinks (and as such they don't want to affect the structure when they created symlinks), but I don't think this is the most common behavior (and if it is, then programs probably need to have a flag determining on whether to use it or not (for instance, I know vite from javascript has a resolve.preserveSymlinks setting so that the user can decide if they want it or not) -- although it's also true that most users don't even care, because they don't put their source code in a symlink or Windows subst 😊

January 21, 2025 07:33 AM UTC


EuroPython

Calls for Proposals Is Open and We Want YOU in Prague

📝 Calls for Proposals 

The call for proposals for EuroPython 2025 is OPEN! 🎉 Similar to last year we will have a mixture of tutorials, talks and posters.

We are looking for sessions of all levels: beginner, intermediate, and advanced.

No matter your level of Python or public speaking experience, EuroPython&aposs job is to help you bring yourself to our community so we all flourish and benefit from each other&aposs experience and contribution. 🏆

The deadline for submission is 27th January, 2025 23:59 UTC.

We would love to see your proposals bubbling in there. Help us make 2025 the year of another incredible EuroPython!

Remember that the sooner you submit your proposals, you will have an option to hear back from us with some feedback to improve your proposal.

For more information, have a look at https://ep2025.europython.eu/programme/cfp.

How to Write a Strong EuroPython Proposal 

Unsure how to write a proposal? Our program committee recorded a video to help you structure your ideas and make your proposal stand out.

Watch it here:

🦒Speaker Mentorship Programme - Closes Today! 

The Mentorship Programme is back for EuroPython 2025!

As a diverse and inclusive community EuroPython offers support for potential speakers who want help preparing for their contribution. To achieve this, we are running the Speaker Mentorship Programme again.

We’re looking for mentors to help our mentees craft great proposals and, if accepted, help them prepare their talks. If you are interested in helping mentees as their mentor, please register here: https://forms.gle/Wbn9Z7zBQtK56xjS9 

If you need support with speaking at EuroPython—especially if you’re from an underrepresented or marginalized group in the tech industry—we encourage you to apply below to become a mentee. https://forms.gle/HgyoWnp3sc89S5DbA

After the CfP, we will host an online panel session with 2–3 experienced community members who will share their advice with first-time speakers. At the end of the panel, there will be a Q&A session to answer all the participants’ questions.

You can watch the recording of the previous year’s workshop here:

💞 Want to Sponsor?

EuroPython is one of the largest Python conferences in Europe, and it wouldn’t be possible without our sponsors. We are so grateful for the companies who have already expressed interest. If you’re interested in sponsoring EuroPython 2025 as well, please reach out to us at sponsoring@europython.eu.

🏛️ EuroPython Society 

Board Report 

The EuroPython conference wouldn’t be what it is without the incredible volunteers who make it all happen. Behind the scenes, there’s also the EuroPython Society—a volunteer-led non-profit that manages the fiscal and legal aspects of running the conference, oversees its organization, and works on a few smaller projects like the grants programme. To keep everyone in the loop and promote transparency, the Board has decided to start sharing regular updates on what we’re working on. And guess what? The December board report is ready: https://www.europython-society.org/board-report-for-december-2024/

We are sponsoring

The mission of the EuroPython Society is to support Python communities across Europe, and we’re excited to sponsor PyCon+Web 2025, happening January 24–25 in Berlin. If you’re attending and want to be the first to get EP 2025 stickers, stop by the community stands.

💗 Community Spotlight 

At the recent Prague Python meetup Pyvo, one of our co-organizers, Honza Král, gave an inspiring lightning talk encouraging others to submit a proposal. A big thank you to the local community for their support in spreading the word!

Are you attending any tech meetups or conferences? If so, we’d appreciate your help in letting others know that our Call for Proposals is still open. 

🙏 We need YOUR help! 

To create the best conference, we need the best program—and for that, we need your help! Spread the word that the call for proposals is open by liking, commenting on, and sharing our posts:

Do you know someone who would make a great speaker? Encourage them to submit a proposal! Have something to share but feeling unsure? Send anyway—we’d love to hear from you!

Are you a previous speaker? Help us invite more amazing speakers by sharing your unique experience. Some of our past speakers are already sharing their experiences on social media. 

If you&aposd like to join in, record a short video and share it with your network! Don’t forget to tag us so we can reshare it!

Not a fan of being on camera? No problem—help us out by sharing your experience in writing! Post about it on social media.

Thank you for helping us make this conference the best it can be!

📅 Upcoming Events in the Python Community

January 21, 2025 07:00 AM UTC

January 20, 2025


Real Python

Getters and Setters: Manage Attributes in Python

Getter and setter methods allow you to access and mutate non-public attributes while maintaining encapsulation. In Python, you’ll typically expose attributes as part of your public API and use properties when you need attributes with functional behavior. This tutorial guides you through writing getter and setter methods, replacing them with properties, and exploring alternatives like descriptors for optimized attribute management.

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

  • Getter and setter methods allow you to access and modify data attributes while maintaining encapsulation.
  • Python properties can replace getters and setters, providing a more Pythonic way to manage attributes with functional behavior.
  • You typically avoid using getters and setters in Python unless necessary, as properties and descriptors offer more flexible solutions.
  • Descriptors are an advanced Python feature that enable reusable attributes with attached behaviors across different classes.
  • In some scenarios, inheritance limitations may make traditional getters and setters preferable over properties.

Even though properties are the Pythonic way to go, they can have some practical drawbacks. Because of this, you’ll find some situations where getters and setters are preferable over properties. This tutorial will delve into the nuances of using different approaches, equipping you with the knowledge to make informed decisions about attribute management in your classes.

To get the most out of this tutorial, you should be familiar with Python object-oriented programming. It’ll also be a plus if you have basic knowledge of Python properties and descriptors.

Source Code: Click here to get the free source code that shows you how and when to use getters, setters, and properties in Python.

Take the Quiz: Test your knowledge with our interactive “Getters and Setters: Manage Attributes in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Getters and Setters: Manage Attributes in Python

In this quiz, you'll test your understanding of Python's getter and setter methods, as well as properties. You'll learn when to use these tools and how they can help maintain encapsulation in your classes.

Getting to Know Getter and Setter Methods

When you define a class in object-oriented programming (OOP), you’ll likely end up with some instance and class attributes. These attributes are just variables that you can access through the instance, the class, or both.

Attributes hold the internal state of objects. In many cases, you’ll need to access and mutate this state, which involves accessing and mutating the attributes. Typically, you’ll have at least two ways to access and mutate attributes. You can either:

  1. Access and mutate the attribute directly
  2. Use methods to access and mutate the attribute

If you expose the attributes of a class to your users, then those attributes automatically become part of the class’s public API. They’ll be public attributes, which means that your users will directly access and mutate the attributes in their code.

Having an attribute that’s part of a class’s API will become a problem if you need to change the internal implementation of the attribute itself. A clear example of this issue is when you want to turn a stored attribute into a computed one. A stored attribute will immediately respond to access and mutation operations by just retrieving and storing data, while a computed attribute will run computations before such operations.

The problem with regular attributes is that they can’t have an internal implementation because they’re just variables. So, changing an attribute’s internal implementation will require converting the attribute into a method, which will probably break your users’ code. Why? Because they’ll have to change attribute access and mutation operations into method calls throughout their codebase if they want the code to continue working.

To deal with this kind of issue, some programming languages, like Java and C++, require you to provide methods for manipulating the attributes of your classes. These methods are commonly known as getter and setter methods. You can also find them referred to as accessor and mutator methods.

What Are Getter and Setter Methods?

Getter and setter methods are quite popular in many object-oriented programming languages. So, it’s pretty likely that you’ve heard about them already. As a rough definition, you can say that getters and setters are:

  • Getter: A method that allows you to access an attribute in a given class
  • Setter: A method that allows you to set or mutate the value of an attribute in a class

In OOP, the getter and setter pattern suggests that public attributes should be used only when you’re sure that no one will ever need to attach behavior to them. If an attribute is likely to change its internal implementation, then you should use getter and setter methods.

Implementing the getter and setter pattern requires:

  1. Making your attributes non-public
  2. Writing getter and setter methods for each attribute

For example, say that you need to write a Label class with text and font attributes. If you were to use getter and setter methods to manage these attributes, then you’d write the class like in the following code:

Python label.py
class Label:
    def __init__(self, text, font):
        self._text = text
        self._font = font

    def get_text(self):
        return self._text

    def set_text(self, value):
        self._text = value

    def get_font(self):
        return self._font

    def set_font(self, value):
        self._font = value
Copied!

In this example, the constructor of Label takes two arguments, text and font. These arguments are stored in the ._text and ._font non-public instance attributes, respectively.

Then you define getter and setter methods for both attributes. Typically, getter methods return the target attribute’s value, while setter methods take a new value and assign it to the underlying attribute.

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


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

January 20, 2025 02:00 PM UTC


Zato Blog

Converting SOAP and WSDL into REST APIs

Converting SOAP and WSDL into REST APIs

Even if most of new APIs today are built around REST, there are still already existing, production applications and systems that expose their APIs using SOAP and WSDL only - in today's article we are integrating with a SOAP service in order to expose it as a REST interface to external applications.

WSDL

WSDL is the language which describes how to invoke SOAP-based applications, using what input, under what address and what output to expect. In the article, we are using a public endpoint whose WSDL you can download here.

Once downloaded, import the WSDL into a tool such as Enterprise Architect or Eclipse to browse its contents. You can also import it to SoapUI to invoke the same service that we are going to access from Zato and Python later on.

Zato Dashboard

The first step is to create a new outgoing SOAP connection in Zato web-admin - simply fill out the form, pointing it to the location of the WSDL resource that contains the description of the remote endpoint.

Once this is done, you will notice a series of entries in the Zato server log, confirming that a queue of connections to the SOAP endpoint has been created successfully.

Python code

We can now author the code needed for the transformation of SOAP into JSON - for simplicity, we are invoking only one specific SOAP service here (LanguageISOCode) but in a full integration project, it would be easy to automate the whole process and have a single transformation service, translating JSON calls into SOAP and the other way around.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class SOAPTransformer(Service):
    name = 'api.soap.transformer'

    class SimpleIO:
        input = 'lang_name'
        output = 'lang_code'
        response_elem = None

    def handle(self):

        # Name of the SOAP connection pool to use
        conn_name = 'My SOAP Endpoint'

        # Obtain a client from the queue ..
        with self.outgoing.soap.get(conn_name).conn.client() as client:

            # .. prepare input data ..
            lang_name = self.request.input.lang_name

            # .. invoke the SOAP service ..
            lang_code = client.service.LanguageISOCode(lang_name)

            # .. log the result received ..
            self.logger.info('SOAP response: `%s`', lang_code)

            # .. and return the result to our caller.
            self.response.payload.lang_code = lang_code

API channel

After deploying the service above, we can create a REST API channel for it.

Invoking the REST endpoint

Now, it is possible to invoke the REST endpoint - let's use curl to do just that:

WSDL reloading

We are almost done but there is still one point to keep in mind - when a WSDL changes, e.g. when a SOAP endpoint's service modifies its input or output, you need to reload the WSDL in Zato so as to load in the newest updates.

You can do it in web-admin too - go to Connections -> SOAP and click Reload WSDL, as below:

Now we are really through although we could very well go further. For instance, we can add multiple REST channels, handle multiple SOAP backend endpoints or turn WSDL-based services into OpenAPI-based ones. These are all valid subjects but they are left for future articles.

More resources

➤ Python API integration tutorial
What is an integration platform?
Python Integration platform as a Service (iPaaS)
What is an Enterprise Service Bus (ESB)? What is SOA?
Open-source iPaaS in Python

January 20, 2025 08:00 AM UTC


Michael Foord

The Absolute Minimum Every Python Web Application Developer Must Know About Security

Python Web Application Security

The Open Source Initiative (OST) is the authority that defines Open Source. They’ve published my guide to security for Python web applications as a three part series. *“The Absolute Minimum Every Python Web Application Developer Must Know About Security”.

Never store passwords in plain text. At a minimum you should be storing salted hashed passwords (which is probably what went wrong in the image here), even better use a key derivation function, but best of all delegate password management to a modern framework and keep it up to date. And never implement your own cryptography algorithms.

Data should be encrypted in transit and at rest. Just stealing your database shouldn’t reveal sensitive information because data is encrypted at rest. You can do this with the StringEncryptedType for SQLAlchemy for example. mTLS (Mutual TLS) is how we can keep data encrypted in transit, even on our internal networks. Just getting access to your network shouldn’t reveal any sensitive information because data is encrypted in transit.

These are just a few of the principles from a Defence in Depth, multi-layered, approach to security explored in this article series:

(Being able to talk about the Blowfish Cipher and the Diffie-Hellmann Elliptic Curve Key Exchange Protocol is cyberpunk, so these articles are teaching real life skills.)

Thanks to Dr David Cassandra Mertz and PyDanny (Daniel Greenfeld) for improving these articles through technical review and to Nick Vidal (and volunteers) from the OSI for their work editing and formatting the articles.

January 20, 2025 12:00 AM UTC

New Python Knowledge Share Video Online: List Comprehensions, Generator Expressions & Function Signatures

.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }

A new one hour Knowledge Share video is online on YouTube.

This session is on working with data using enumerate, zip plus list comprehensions and generator expressions. Along the way we’ll talk about tuple unpacking, set and dictionary comprehensions and even nested list comprehensions.

We finish off with a look at function signatures: required and optional arguments plus positional and keyword arguments and positional only and keyword only arguments.

The slides/presentation can be downloaded here:

You can see all the sessions, eight so far, on a range of Python topics from generators to concurrency to testing with pytest on YouTube:

January 20, 2025 12:00 AM UTC

January 19, 2025


Django Weblog

Django earns the CHAOSS DEI Bronze badge 🫶

We’re excited to announce that Django has been awarded the CHAOSS Diversity, Equity, and Inclusion (DEI) Bronze Badge!

Trophy with confetti, CHAOSS DEI Bronze badge, Django logo

This badge reflects our ongoing commitment to fostering a diverse, equitable, and inclusive community for all Djangonauts. It’s part of the CHAOSS DEI Project Badging initiative.

Our new Diversity, Equity, and Inclusion Project Statement details all the ways in which we want to create an environment where everyone can participate and thrive, and complements our pre-existing Django Community Diversity Statement. From inclusive leadership structures to Django events, we strive to ensure our community is welcoming, transparent, and supportive.

Thank you to everyone in the Django community who contributes to making our project inclusive, accessible, and welcoming 🫶. Thank you to Sarah Boyce, who led the work for us to be awarded this badge as part of . We view this milestone as part of a continuous journey for our project and community to improve, and look forward to building an even more vibrant and supportive community together.

January 19, 2025 08:30 PM UTC


Daniel Roy Greenfeld

Fastcore L

An exploration of Fastcore's enhanced list-like structure

January 19, 2025 02:11 PM UTC


Real Python

Python Constants: Improve Your Code's Maintainability

In Python, constants are identifiers for values that don’t change during a program’s execution. Unlike some other languages, Python lacks built-in syntax for constants, treating them as variables that should remain unchanged. You define constants by following a naming convention: use all uppercase letters with underscores separating words. This signals to other developers that these variables should not be reassigned.

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

  • Constants in Python are variables that should remain unchanged throughout execution.
  • Python lacks built-in syntax for constants, relying on conventions to signal immutability.
  • Defining a constant involves using uppercase letters with underscores for clarity.
  • Best practices include defining constants at the top of a file and using descriptive names.
  • Built-in constants like math.pi offer predefined, reliable values, unlike user-defined ones.

To learn the most from this tutorial, you’ll need basic knowledge of Python variables, functions, modules, packages, and namespaces. You’ll also need to know the basics of object-oriented programming in Python.

Sample Code: Click here to download sample code that shows you how to use constants in Python.

Understanding Constants and Variables

Variables and constants are two historical and fundamental concepts in computer programming. Most programming languages use these concepts to manipulate data and work in an effective and logical fashion.

Variables and constants will probably be present in each project, app, library, or other piece of code that you’ll ever write. The question is: what are variables and constants in practice?

What Variables Are

In math, a variable is defined as a symbol that refers to a value or quantity that can change over time. In programming, a variable is also a symbol or name typically associated with a memory address containing a value, object, or piece of data. Like in math, the content of a programming variable can change during the execution of the code that defines it.

Variables typically have a descriptive name that’s somehow associated with a target value or object. This target value can be of any data type. So, you can use variables to represent numbers, strings, sequences, custom objects, and more.

You can perform two main operations on a variable:

  1. Access its value
  2. Assign it a new value

In most programming languages, you can access the value associated with a variable by citing the variable’s name in your code. To assign a new value to a given variable, you’ll use an assignment statement, which often consists of the variable’s name, an assignment operator, and the desired value.

In practice, you’ll find many examples of magnitudes, data, and objects that you can represent as variables. A few examples include temperature, speed, time, and length. Other examples of data that you can treat as variables include the number of registered users in a web app, the number of active characters in a video game, and the number of miles covered by a runner.

What Constants Are

Math also has the concept of constants. The term refers to a value or quantity that never changes. In programming, constants refer to names associated with values that never change during a program’s execution.

Just like variables, programming constants consist of two things: a name and an associated value. The name will clearly describe what the constant is all about. The value is the concrete expression of the constant itself.

Like with variables, the value associated with a given constant can be of any of data type. So, you can define integer constants, floating-point constants, character constants, string constants, and more.

After you’ve defined a constant, it’ll only allow you to perform a single operation on it. You can only access the constant’s value but not change it over time. This is different from a variable, which allows you to access its value, but also reassign it.

You’ll use constants to represent values that won’t change. You’ll find lots of these values in your day-to-day programming. A few examples include the speed of light, the number of minutes in an hour, and the name of a project’s root folder.

Why Use Constants

In most programming languages, constants protect you from accidentally changing their values somewhere in the code when you’re coding at two in the morning, causing unexpected and hard-to-debug errors. Constants also help you make your code more readable and maintainable.

Some advantages of using constants instead of using their values directly in your code include:

Advantage Description
Improved readability A descriptive name representing a given value throughout a program is always more readable and explicit than the bare-bones value itself. For example, it’s easier to read and understand a constant named MAX_SPEED than the concrete speed value itself.
Clear communication of intent Most people will assume that 3.14 may refer to the Pi constant. However, using the Pi, pi, or PI name will communicate your intent more clearly than using the value directly. This practice will allow other developers to understand your code quickly and accurately.
Better maintainability Constants enable you to use the same name to identify the same value throughout your code. If you need to update the constant’s value, then you don’t have to change every instance of the value. You just have to change the value in a single place: the constant definition. This improves your code’s maintainability.
Lower risk of errors A constant representing a given value throughout a program is less error-prone than several explicit instances of the value. Say that you use different precision levels for Pi depending on your target calculations. You’ve explicitly used the values with the required precision for every calculation. If you need to change the precision in a set of calculations, then replacing the values can be error-prone because you can end up changing the wrong values. It’s safer to create different constants for different precision levels and change the code in a single place.
Reduced debugging needs Constants will remain unchanged during the program’s lifetime. Because they’ll always have the same value, they shouldn’t cause errors and bugs. This feature may not be necessary in small projects, but it may be crucial in large projects with multiple developers. Developers won’t have to invest time debugging the current value of any constant.
Thread-safe data storage Constants can only be accessed, not written. This feature makes them thread-safe objects, which means that several threads can simultaneously use a constant without the risk of corrupting or losing the underlying data.

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


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

January 19, 2025 02:00 PM UTC

Python Class Constructors: Control Your Object Instantiation

Creating a class constructor in Python involves understanding the instantiation process, which consists of two steps: instance creation and instance initialization. You start this process by calling the class like a function, which triggers the .__new__() method to create an instance and the .__init__() method to initialize it. Mastering these methods allows you to customize how Python constructs and initializes objects of your classes.

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

  • A class constructor in Python triggers the instantiation process, creating and initializing objects.
  • Python handles instantiation internally with .__new__() for creation and .__init__() for initialization.
  • You can customize object initialization by overriding the .__init__() method in your class.
  • The difference between .__new__() and .__init__() is that .__new__() creates the instance, while .__init__() initializes it.
  • Common use cases for overriding .__new__() include subclassing immutable types or implementing singletons.

To better understand the examples and concepts in this tutorial, you should be familiar with object-oriented programming and special methods in Python.

Free Bonus: Click here to get access to a free Python OOP Cheat Sheet that points you to the best tutorials, videos, and books to learn more about Object-Oriented Programming with Python.

Take the Quiz: Test your knowledge with our interactive “Python Class Constructors: Control Your Object Instantiation” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Python Class Constructors: Control Your Object Instantiation

In this quiz, you'll test your understanding of class constructors in Python. By working through this quiz, you'll revisit the internal instantiation process, object initialization, and fine-tuning object creation.

Python’s Class Constructors and the Instantiation Process

Like many other programming languages, Python supports object-oriented programming. At the heart of Python’s object-oriented capabilities, you’ll find the class keyword, which allows you to define custom classes that can have attributes for storing data and methods for providing behaviors.

Once you have a class to work with, then you can start creating new instances or objects of that class, which is an efficient way to reuse functionality in your code.

Creating and initializing objects of a given class is a fundamental step in object-oriented programming. This step is often referred to as object construction or instantiation. The tool responsible for running this instantiation process is commonly known as a class constructor.

Getting to Know Python’s Class Constructors

In Python, to construct an object of a given class, you just need to call the class with appropriate arguments, as you would call any function:

Python
>>> class SomeClass:
...     pass
...

>>> # Call the class to construct an object
>>> SomeClass()
<__main__.SomeClass object at 0x7fecf442a140>
Copied!

In this example, you define SomeClass using the class keyword. This class is currently empty because it doesn’t have attributes or methods. Instead, the class’s body only contains a pass statement as a placeholder statement that does nothing.

Then you create a new instance of SomeClass by calling the class with a pair of parentheses. In this example, you don’t need to pass any argument in the call because your class doesn’t take arguments yet.

In Python, when you call a class as you did in the above example, you’re calling the class constructor, which creates, initializes, and returns a new object by triggering Python’s internal instantiation process.

A final point to note is that calling a class isn’t the same as calling an instance of a class. These are two different and unrelated topics. To make a class’s instance callable, you need to implement a .__call__() special method, which has nothing to do with Python’s instantiation process.

Understanding Python’s Instantiation Process

You trigger Python’s instantiation process whenever you call a Python class to create a new instance. This process runs through two separate steps, which you can describe as follows:

  1. Create a new instance of the target class
  2. Initialize the new instance with an appropriate initial state

To run the first step, Python classes have a special method called .__new__(), which is responsible for creating and returning a new empty object. Then another special method, .__init__(), takes the resulting object, along with the class constructor’s arguments.

The .__init__() method takes the new object as its first argument, self. Then it sets any required instance attribute to a valid state using the arguments that the class constructor passed to it.

In short, Python’s instantiation process starts with a call to the class constructor, which triggers the instance creator, .__new__(), to create a new empty object. The process continues with the instance initializer, .__init__(), which takes the constructor’s arguments to initialize the newly created object.

To explore how Python’s instantiation process works internally, consider the following example of a Point class that implements a custom version of both methods, .__new__() and .__init__(), for demonstration purposes:

Python point.py
 1class Point:
 2    def __new__(cls, *args, **kwargs):
 3        print("1. Create a new instance of Point.")
 4        return super().__new__(cls)
 5
 6    def __init__(self, x, y):
 7        print("2. Initialize the new instance of Point.")
 8        self.x = x
 9        self.y = y
10
11    def __repr__(self) -> str:
12        return f"{type(self).__name__}(x={self.x}, y={self.y})"
Copied!

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


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

January 19, 2025 02:00 PM UTC

Create and Modify PDF Files in Python

Creating and modifying PDF files in Python is straightforward with libraries like pypdf and ReportLab. You can read, manipulate, and create PDF files using these tools. pypdf lets you extract text, split, merge, rotate, crop, encrypt, and decrypt PDFs. ReportLab enables you to create new PDFs from scratch, allowing customization with fonts and page sizes.

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

  • You can read and modify existing PDF files using pypdf in Python.
  • You can create new PDF files from scratch with the ReportLab library.
  • Methods to encrypt and decrypt a PDF file with a password are available in pypdf.
  • Concatenating and merging multiple PDF files can be done using pypdf.
  • You can add custom fonts to a PDF using ReportLab.
  • Python can create interactive PDFs with forms using ReportLab.

To follow along with this tutorial, you should download and extract to your home folder the materials used in the examples. To do this, click the link below:

Download the sample materials: Click here to get the materials you’ll use to learn about creating and modifying PDF files in this tutorial.

Extracting Text From PDF Files With pypdf

In this section, you’ll learn how to read PDF files and extract their text using the pypdf library. Before you can do that, though, you need to install it with pip:

Shell
$ python -m pip install pypdf
Copied!

With this command, you download and install the latest version of pypdf from the Python package index (PyPI). To verify the installation, go ahead and run the following command in your terminal:

Shell
$ python -m pip show pypdf
Name: pypdf
Version: 3.8.1
Summary: A pure-python PDF library capable of splitting,
 merging, cropping, and transforming PDF files
Home-page:
Author:
Author-email: Mathieu Fenniak <biziqe@mathieu.fenniak.net>
License:
Location: .../lib/python3.10/site-packages
Requires:
Required-by:
Copied!

Pay particular attention to the version information. At the time of publication for this tutorial, the latest version of pypdf was 3.8.1. This library has gotten plenty of updates lately, and cool new features are added quite frequently. Most importantly, you’ll find many breaking changes in the library’s API if you compare it with its predecessor library PyPDF2.

Before diving into working with PDF files, you must know that this tutorial is adapted from the chapter “Creating and Modifying PDF Files” in Python Basics: A Practical Introduction to Python 3.

The book uses Python’s built-in IDLE editor to create and edit Python files and interact with the Python shell, so you’ll find occasional references to IDLE throughout this tutorial. However, you should have no problems running the example code from the editor and environment of your choice.

Reading PDF Files With PdfReader

To kick things off, you’ll open a PDF file and read some information about it. You’ll use the Pride_and_Prejudice.pdf file provided in the downloadable resources for this tutorial.

Open IDLE’s interactive window and import the PdfReader class from pypdf:

Python
>>> from pypdf import PdfReader
Copied!

To create a new instance of the PdfReader class, you’ll need to provide the path to the PDF file that you want to open. You can do that using the pathlib module:

Python
>>> from pathlib import Path

>>> pdf_path = (
...     Path.home()
...     / "creating-and-modifying-pdfs"
...     / "practice_files"
...     / "Pride_and_Prejudice.pdf"
... )
Copied!

The pdf_path variable now contains the path to a PDF version of Jane Austen’s Pride and Prejudice.

Note: You may need to change pdf_path so that it corresponds to the location of the creating-and-modifying-pdfs/ folder on your computer.

Now create the PdfReader instance by calling the class’s constructor with the path to your PDF file as an argument:

Python
>>> pdf_reader = PdfReader(pdf_path)
Copied!

If you’ve been following along in Python Basics, then you’ll remember from Chapter 12, “File Input and Output,” that all open files should be closed before a program terminates. The PdfReader object does all of this for you, so you don’t need to worry about opening or closing the PDF file!

Now that you’ve created a PdfReader instance, you can use it to gather information about the PDF file. For example, to get the number of pages contained in the PDF file, you can use the built-in len() function like in the code below:

Read the full article at https://realpython.com/creating-modifying-pdf/ »


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

January 19, 2025 02:00 PM UTC

How to Install Python on Your System: A Guide

Installing Python on your system involves a few straightforward steps. First, check if Python is already installed by opening a command-line interface and typing python --version or python3 --version. You can install Python on Windows using the official installer from Python.org or through the Microsoft Store. On macOS, you can use the official installer or Homebrew. For Linux, use your package manager or build Python from source.

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

  • Check if Python is installed by running python --version or python3 --version in a command-line interface.
  • Upgrade Python by downloading and installing the latest version from Python.org.
  • Install and manage multiple Python versions with pyenv to keep them separate.

This tutorial covers installing the latest Python on the most important platforms or operating systems, such as Windows, macOS, Linux, iOS, and Android. However, it doesn’t cover all the existing Linux distributions, as that would be a massive task. Nevertheless, you’ll find instructions for the most popular distributions available today.

To get the most out of this tutorial, you should be comfortable using your operating system’s terminal or command line.

Free Bonus: Click here to get a Python Cheat Sheet and learn the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.

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


Interactive Quiz

Python Installation and Setup

In this quiz, you'll test your understanding of how to install or update Python on your computer. With this knowledge, you'll be able to set up Python on various operating systems, including Windows, macOS, and Linux.

Windows: How to Check or Get Python

In this section, you’ll learn to check whether Python is installed on your Windows operating system (OS) and which version you have. You’ll also explore three installation options that you can use on Windows.

Note: In this tutorial, you’ll focus on installing the latest version of Python in your current operating system (OS) rather than on installing multiple versions of Python. If you want to install several versions of Python in your OS, then check out the Managing Multiple Python Versions With pyenv tutorial. Note that on Windows machines, you’d have to use pyenv-win instead of pyenv.

For a more comprehensive guide on setting up a Windows machine for Python programming, check out Your Python Coding Environment on Windows: Setup Guide.

Checking the Python Version on Windows

To check whether you already have Python on your Windows machine, open a command-line application like PowerShell or the Windows Terminal.

Follow the steps below to open PowerShell on Windows:

  1. Press the Win key.
  2. Type PowerShell.
  3. Press Enter.

Alternatively, you can right-click the Start button and select Windows PowerShell or Windows PowerShell (Admin). In some versions of Windows, you’ll find Terminal or Terminal (admin).

Note: To learn more about your options for the Windows terminal, check out Using the Terminal on Windows.

With the command line open, type in the following command and press the Enter key:

Windows PowerShell
PS> python --version
Python 3.x.z
Copied!

Using the --version switch will show you the installed version. Note that the 3.x.z part is a placeholder here. In your machine, x and z will be numbers corresponding to the specific version you have installed.

Alternatively, you can use the -V switch:

Windows PowerShell
PS> python -V
Python 3.x.z
Copied!

Using the python -V or python—-version command, you can check whether Python is installed on your system and learn what version you have. If Python isn’t installed on your OS, you’ll get an error message.

Knowing the Python Installation Options on Windows

You’ll have different options to install Python if you’re on a Windows machine. Here are three popular ones:

Read the full article at https://realpython.com/installing-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 ]

January 19, 2025 02:00 PM UTC

pandas GroupBy: Your Guide to Grouping Data in Python

The pandas .groupby() method allows you to efficiently analyze and transform datasets when working with data in Python. With df.groupby(), you can split a DataFrame into groups based on column values, apply functions to each group, and combine the results into a new DataFrame. This technique is essential for tasks like aggregation, filtering, and transformation on grouped data.

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

  • Calling .groupby("column_name") splits a DataFrame into groups, applies a function to each group, and combines the results.
  • To group by multiple columns, you can pass a list of column names to .groupby().
  • Common aggregation methods in pandas include .sum(), .mean(), and .count().
  • You can use custom functions with pandas .groupby() to perform specific operations on groups.

This tutorial assumes that you have some experience with pandas itself, including how to read CSV files into memory as pandas objects with read_csv(). If you need a refresher, then check out Reading CSVs With pandas and pandas: How to Read and Write Files.

You can download the source code for all the examples in this tutorial by clicking on the link below:

Download Datasets: Click here to download the datasets that you’ll use to learn about pandas’ GroupBy in this tutorial.

Prerequisites

Before you proceed, make sure that you have the latest version of pandas available within a new virtual environment:

Windows PowerShell
PS> python -m venv venv
PS> venv\Scripts\activate
(venv) PS> python -m pip install pandas
Copied!
Shell
$ python3 -m venv venv
$ source venv/bin/activate
(venv) $ python -m pip install pandas
Copied!

In this tutorial, you’ll focus on three datasets:

  1. The U.S. Congress dataset contains public information on historical members of Congress and illustrates several fundamental capabilities of .groupby().
  2. The air quality dataset contains periodic gas sensor readings. This will allow you to work with floats and time series data.
  3. The news aggregator dataset holds metadata on several hundred thousand news articles. You’ll be working with strings and doing text munging with .groupby().

You can download the source code for all the examples in this tutorial by clicking on the link below:

Download Datasets: Click here to download the datasets that you’ll use to learn about pandas’ GroupBy in this tutorial.

Once you’ve downloaded the .zip file, unzip the file to a folder called groupby-data/ in your current directory. Before you read on, ensure that your directory tree looks like this:

./
│
└── groupby-data/
    │
    ├── legislators-historical.csv
    ├── airqual.csv
    └── news.csv

With pandas installed, your virtual environment activated, and the datasets downloaded, you’re ready to jump in!

Example 1: U.S. Congress Dataset

You’ll jump right into things by dissecting a dataset of historical members of Congress. You can read the CSV file into a pandas DataFrame with read_csv():

Python pandas_legislators.py
import pandas as pd

dtypes = {
    "first_name": "category",
    "gender": "category",
    "type": "category",
    "state": "category",
    "party": "category",
}
df = pd.read_csv(
    "groupby-data/legislators-historical.csv",
    dtype=dtypes,
    usecols=list(dtypes) + ["birthday", "last_name"],
    parse_dates=["birthday"]
)
Copied!

The dataset contains members’ first and last names, birthday, gender, type ("rep" for House of Representatives or "sen" for Senate), U.S. state, and political party. You can use df.tail() to view the last few rows of the dataset:

Python
>>> from pandas_legislators import df
>>> df.tail()
      last_name first_name   birthday gender type state       party
11970   Garrett     Thomas 1972-03-27      M  rep    VA  Republican
11971    Handel      Karen 1962-04-18      F  rep    GA  Republican
11972     Jones     Brenda 1959-10-24      F  rep    MI    Democrat
11973    Marino        Tom 1952-08-15      M  rep    PA  Republican
11974     Jones     Walter 1943-02-10      M  rep    NC  Republican
Copied!

The DataFrame uses categorical dtypes for space efficiency:

Python
>>> df.dtypes
last_name             object
first_name          category
birthday      datetime64[ns]
gender              category
type                category
state               category
party               category
dtype: object
Copied!

You can see that most columns of the dataset have the type category, which reduces the memory load on your machine.

Read the full article at https://realpython.com/pandas-groupby/ »


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

January 19, 2025 02:00 PM UTC


Seth Michael Larson

How to disable Copilot in GitHub

For the first time in months GitHub has released a feature that I actually enjoy: a way to disable Copilot on the home screen. Thanks to Harry Sintonen for sharing this on Mastodon: Login to github.com Profile -> Settings -> Copilot "Dashboard entry point" -> Select "Disabled" While you're here, disable the rest. Don't forget to leave any feedback you have in the (...) menu, too. I am not holding my breath that GitHub will start delivering more features that actually benefit users any time soon (GitHub Security Advisories? Remember that feature?) Seeing a cascade of users disabling Copilot might provide enough signal that they are wasting their time pushing these useless features down everyone's throats.

January 19, 2025 12:00 AM UTC


Armin Ronacher

Automatic Server Reloading in Rust on Change: What is listenfd/systemfd?

When I developed Werkzeug (and later Flask), the most important part of the developer experience for me was enabling fast, automatic reloading. Werkzeug (and with it Flask), this is achieved by using two procsses at all times. The parent process holds on to the file descriptor of the socket on which the server listens, and a subprocess picks up that file descriptor. That subprocess restarts when it detects changes. This ensures that no matter what happens, there is no window where the browser reports a connection error. At worst, the browser will hang until the process finishes reloading, after which the page loads successfully. In case the inner process fails to come up during restarts, you get an error message.

A few years ago, I wanted to accomplish the same experience for working with Rust code which is why I wrote systemfd and listenfd. I however realized that I never really wrote here about how they work and disappointingly I think those crates, and a good auto-reloading experience in Rust are largely unknown.

Watching for Changes

Firstly one needs to monitor the file system for changes. While in theory I could have done this myself, there was already a tool that could do that.

At the time there was cargo watch. Today one might instead use it together with the more generic watchexec. Either one monitor your workspace for changes and then executes a command. So you can for instance tell it to restart your program. One of these will work:

watchexec -r -- cargo run
cargo watch -x run

You will need a tool like that to do the watching part. At this point I recommend the more generic watchexec which you can find on homebrew and elsewhere.

Passing Sockets

But what about the socket? The solution to this problem I picked comes from systemd. Systemd has a “protocol” that standardizes passing file descriptors from one process to another through environment variables. In systemd parlance this is called “socket activation,” as it allows systemd to only launch a program if someone started making a request to the socket. This concept was originally introduced by Apple as part of launchd.

To make this work with Rust, I created two crates:

  • systemfd is the command line tool that opens sockets and passes them on to other programs.
  • listenfd is a Rust crate that accepts file descriptors from systemd or systemfd.

It's worth noting that systemfd is not exclusivly useful to Rust. The systemd protocol can be implemented in other languages as well, meaning that if you have a socket server written in Go or Python, you can also use systemfd.

So here is how you use it.

First you need to add listenfd to your project:

cargo add listenfd

Then, modify your server code to accept sockets via listenfd before falling back to listening itself on ports provided through command-line arguments or configuration files. Here is an example using listenfd in axum:

use axum::{routing::get, Router};
use tokio::net::TcpListener;

async fn index() -> &'static str {
    "Hello, World!"
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let app = Router::new().route("/", get(index));

    let mut listenfd = listenfd::ListenFd::from_env();
    let listener = match listenfd.take_tcp_listener(0)? {
        Some(listener) => TcpListener::from_std(listener),
        None => TcpListener::bind("0.0.0.0:3000").await,
    }?;

    axum::serve(listener, app).await?;
    Ok(())
}

The key point here is to accept socket 0 from the environment as a TCP listener and use it if available. If the socket is not provided (e.g. when launched without systemd/systemfd), the code falls back to opening a fixed port.

Putting it Together

Finally you can use cargo watch / watchexec together with systemfd:

systemfd --no-pid -s http::8888 -- watchexec -r -- cargo run
systemfd --no-pid -s http::8888 -- cargo watch -x run

This is what the parameters mean:

  • systemfd needs to be first it's the program that opens the sockets.
  • --no-pid is a flag prevents the PID from being passed. This is necessary for listenfd to accept the socket. This is a departure of the socket passing protocol from systemd which otherwise does not allow ports to be passed through another program (like watchexec). In short: when the PID information is not passed, then listenfd will accept the socket regardless. Otherwise it would only accept it from the direct parent process.
  • -s http::8888 tells systemfd to open one TCP socket on port 8888. Using http instead of tcp is a small improvement that will cause systemfd to print out a URL on startup.
  • -- watchexec -r makes watchexec restart the process when something changes in the current working directory.
  • -- cargo run is the program that watchexec will start and re-start onm changes. In Rust this will first compile the changes and then run the application. Because we put listenfd in, it will try to first accept the socket from systemfd.

The end result is that you can edit your code, and it will recompile automatically and restart the server without dropping any requests. When you run it, and perform changes, it will look a bit like this:

$ systemfd --no-pid -s http::5555 -- watchexec -r -- cargo run
~> socket http://127.0.0.1:5555/ -> fd #3
[Running: cargo run]
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/axum-test`
[Running: cargo run]
   Compiling axum-test v0.1.0 (/private/tmp/axum-test)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.52s
     Running `target/debug/axum-test`

For easier access, I recommend putting this into a Makefile or similar so you can just run make devserver and it runs the server in watch mode.

To install systemfd you can use curl to bash:

curl -sSfL https://github.com/mitsuhiko/systemfd/releases/latest/download/systemfd-installer.sh | sh

What About Windows?

Now how does this work on Windows? The answer is that systemfd and listenfd have a custom, proprietary protocol that also makes socket passing work on Windows. That's a more complex system which involves a local RPC server. However the system does also support Windows and the details about how it works are largely irrelevant for you as a user — unless you want to implement that protocol for another programming language.

Potential Improvements

I really enjoy using this combination, but it can be quite frustrating to require so many commands, and the command line workflow isn't optimal. Ideally, this functionality would be better integrated into specific Rust frameworks like axum and provided through a dedicated cargo plugin. In a perfect world, one could simply run cargo devserver, and everything would work seamlessly.

However, maintaining such an integrated experience is a much more involved effort than what I have. Hopefully, someone will be inspired to further enhance the developer experience and achieve deeper integration with Rust frameworks, making it more accessible and convenient for everyone.

January 19, 2025 12:00 AM UTC

January 18, 2025


Real Python

Understanding the Python Mock Object Library

Mocking in Python with unittest.mock allows you to simulate complex logic or unpredictable dependencies, such as responses from external services. You create mock objects to replace real ones in your tests, ensuring that your tests are isolated. The Mock class allows you to imitate real objects, and the patch() function lets you temporarily substitute mocks for real objects in your tests.

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

  • A mock in Python is a substitute object that simulates a real object in a testing environment.
  • Mock differs from MagicMock in that MagicMock includes implementations of most magic methods.
  • The patch() function replaces real objects with mock instances, controlling the scope of mocking.
  • You can assert if a Mock object was called with methods like .assert_called().
  • You set a mock’s return value by assigning a value to the mock’s .return_value attribute.

In this tutorial, you’ll explore how mocking enhances your testing strategy by enabling controlled and predictable test environments for your Python code. When you can control the behavior of your code during testing, you can reliably test that your application logic is correct.

Get Your Code: Click here to download the free sample code that you’ll use to learn about Python’s mock object library.

Take the Quiz: Test your knowledge with our interactive “Understanding the Python Mock Object Library” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Understanding the Python Mock Object Library

In this quiz, you'll test your understanding of Python's unittest.mock library. With this knowledge, you'll be able to write robust tests, create mock objects, and ensure your code is reliable and efficient.

What Is Mocking?

A mock object substitutes and imitates a real object within a testing environment. Using mock objects is a versatile and powerful way to improve the quality of your tests. This is because by using Python mock objects, you can control your code’s behavior during testing.

For example, if your code makes HTTP requests to external services, then your tests execute predictably only so far as the services are behaving as you expected. Sometimes, a temporary change in the behavior of these external services can cause intermittent failures within your test suite.

Because of this, it would be better for you to test your code in a controlled environment. Replacing the actual request with a mock object would allow you to simulate external service outages and successful responses in a predictable way.

Sometimes, it’s difficult to test certain areas of your codebase. Such areas include except blocks and if statements that are hard to satisfy. Using Python mock objects can help you control the execution path of your code to reach these areas and improve your code coverage.

Another reason to use mock objects is to better understand how you’re using their real counterparts in your code. A Python mock object contains data about its usage that you can inspect, such as:

  • If you called a method
  • How you called the method
  • How often you called the method

Understanding what a mock object does is the first step to learning how to use one. Next, you’ll explore the Python mock object library to see how to use Python mock objects.

The Python Mock Library

Python’s built-in mock object library is unittest.mock. It provides an easy way to introduce mocks into your tests.

Note: The standard library includes unittest.mock starting from Python 3.3 and in all newer versions. If you’re using an older version of Python, then you’ll need to install the official backport of the library.

To do so, install mock from the Python Package Index (PyPI) using pip:

Shell
$ python -m pip install mock
Copied!

You may want to create and activate a virtual environment before installing the package.

unittest.mock provides a class called Mock, which you’ll use to imitate real objects in your codebase. Mock, along with its subclasses, offers incredible flexibility and insightful data that will meet most of your Python mocking needs.

The library also provides a function called patch(), which replaces the real objects in your code with Mock instances. You can use patch() as either a decorator or a context manager, giving you control over the scope in which the object will be mocked. Once the designated scope exits, patch() will clean up your code by replacing the mocked objects with their original counterparts.

Finally, unittest.mock provides solutions for some of the issues inherent in mocking objects, which you’ll explore later in this tutorial.

Now that you have a better understanding of what mocking is and the library you’ll be using, it’s time to dive in and explore the features and functionalities unittest.mock has to offer.

The Mock Object

unittest.mock offers a base class for mocking objects called Mock. The use cases for Mock are practically limitless because Mock is so flexible.

Begin by instantiating a new Mock instance:

Python
>>> from unittest.mock import Mock
>>> mock = Mock()
>>> mock
<Mock id='4561344720'>
Copied!

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


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

January 18, 2025 02:00 PM UTC

NumPy's max() and maximum(): Find Extreme Values in Arrays

NumPy’s max() function efficiently finds maximum values within an array, making it a key tool for data analysis in Python. This tutorial guides you through using max() and maximum(), handling missing values, and explores advanced features like broadcasting for comparing arrays of different shapes.

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

  • NumPy’s max() function finds the maximum value within a single array, working with both one-dimensional and multi-dimensional arrays.
  • Conversely, np.maximum() compares two arrays element-wise to find the maximum values.
  • np.amax() and max() are equivalent in NumPy.
  • You can use np.nanmax() to find the maximum value in an array while ignoring nan values, preventing them from affecting the result.

This tutorial includes a very short introduction to NumPy, so even if you’ve never used NumPy before, you should be able to jump right in.

With the background provided here, you’ll be ready to continue exploring the wealth of functionality to be found in the NumPy library.

Free Bonus: Click here to get access to a free NumPy Resources Guide that points you to the best tutorials, videos, and books for improving your NumPy skills.

NumPy: Numerical Python

NumPy is short for Numerical Python. It’s an open source Python library that enables a wide range of applications in the fields of science, statistics, and data analytics through its support of fast, parallelized computations on multidimensional arrays of numbers. Many of the most popular numerical packages use NumPy as their base library.

Introducing NumPy

The NumPy library is built around a class named np.ndarray and a set of methods and functions that leverage Python syntax for defining and manipulating arrays of any shape or size.

NumPy’s core code for array manipulation is written in C. You can use functions and methods directly on an ndarray as NumPy’s C-based code efficiently loops over all the array elements in the background. NumPy’s high-level syntax means that you can simply and elegantly express complex programs and execute them at high speeds.

You can use a regular Python list to represent an array. However, NumPy arrays are far more efficient than lists, and they’re supported by a huge library of methods and functions. These include mathematical and logical operations, sorting, Fourier transforms, linear algebra, array reshaping, and much more.

Today, NumPy is in widespread use in fields as diverse as astronomy, quantum computing, bioinformatics, and all kinds of engineering.

NumPy is used under the hood as the numerical engine for many other libraries, such as pandas and SciPy. It also integrates easily with visualization libraries like Matplotlib and seaborn.

NumPy is easy to install with your package manager, for example pip or conda. For detailed instructions plus a more extensive introduction to NumPy and its capabilities, take a look at NumPy Tutorial: Your First Steps Into Data Science in Python or the NumPy Absolute Beginner’s Guide.

In this tutorial, you’ll learn how to take your very first steps in using NumPy. You’ll then explore NumPy’s max() and maximum() commands.

Creating and Using NumPy Arrays

You’ll start your investigation with a quick overview of NumPy arrays, the flexible data structure that gives NumPy its versatility and power.

The fundamental building block for any NumPy program is the ndarray. An ndarray is a Python object wrapping an array of numbers. It may, in principle, have any number of dimensions of any size. You can declare an array in several ways. The most straightforward method starts from a regular Python list or tuple:

Python
>>> import numpy as np
>>> A = np.array([3, 7, 2, 4, 5])
>>> A
array([3, 7, 2, 4, 5])

>>> B = np.array(((1, 4), (1, 5), (9, 2)))
>>> B
array([[1, 4],
       [1, 5],
       [9, 2]])
Copied!

You’ve imported numpy under the alias np. This is a standard, widespread convention, so you’ll see it in most tutorials and programs. In this example, A is a one-dimensional array of numbers, while B is two-dimensional.

Notice that the np.array() factory function expects a Python list or tuple as its first parameter, so the list or tuple must therefore be wrapped in its own set of brackets or parentheses, respectively. Just throwing in an unwrapped bunch of numbers won’t work:

Python
>>> np.array(3, 7, 2, 4, 5)
Traceback (most recent call last):
...
TypeError: array() takes from 1 to 2 positional arguments but 5 were given
Copied!

With this syntax, the interpreter sees five separate positional arguments, so it’s confused.

In your constructor for array B, the nested tuple argument needs an extra pair of parentheses to identify it, in its entirety, as the first parameter of np.array().

Read the full article at https://realpython.com/numpy-max-maximum/ »


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

January 18, 2025 02:00 PM UTC

Get Started With Django: Build a Portfolio App

Django is a powerful Python web framework for creating complex applications. It follows the Model-View-Template (MVT) architecture and includes built-in features like authentication, an admin interface, and database management.

In this tutorial, you’ll create a portfolio app step by step, gaining hands-on experience with Django’s core features. Along the way, you’ll work with models, views, templates, and the admin interface to build a fully functional web application. This hands-on approach will demystify Django’s structure and functionality.

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

  • Django projects begin with setting up a development environment and creating a project structure.
  • Learning HTML and CSS before Django can help with styling templates, but it’s not mandatory.
  • Django is used for building web applications with Python, offering built-in features and scalability.
  • A real-life example of Django is a portfolio website that showcases projects and manages content.

At the end of this tutorial, you’ll have a working portfolio website to showcase your projects. If you’re curious about how the final source code looks, then you can click the link below:

Get Your Code: Click here to download the Python source code for your Django portfolio project.

Take the Quiz: Test your knowledge with our interactive “Get Started With Django: Build a Portfolio App” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Get Started With Django: Build a Portfolio App

In this quiz, you'll test your understanding of Django, a fully featured Python web framework. By working through this quiz, you'll revisit the steps to create a fully functioning web application and learn about some of Django's most important features.

Learn Django

There are endless web development frameworks out there, so why should you learn Django over any of the others? First of all, it’s written in Python, one of the most readable and beginner-friendly programming languages out there.

Note: This tutorial assumes an intermediate knowledge of the Python language. If you’re new to programming with Python, then check out the Python Basics learning path or the introductory course.

The second reason you should learn Django is the scope of its features. When building a website, you don’t need to rely on any external libraries or packages if you choose Django. This means that you don’t need to learn how to use anything else, and the syntax is seamless because you’re using only one framework.

There’s also the added benefit that Django is straightforward to update, since the core functionality is in one package. If you do find yourself needing to add extra features, there are several external libraries that you can use to enhance your site.

One of the great things about the Django framework is its in-depth documentation. It has detailed documentation on every aspect of Django and also has great examples and even a tutorial to get you started.

There’s also a fantastic community of Django developers, so if you get stuck, there’s almost always a way forward by either checking the docs or asking the community.

Django is a high-level web application framework with loads of features. It’s great for anyone new to web development due to its fantastic documentation, and it’s especially great if you’re also familiar with Python.

Understand the Structure of a Django Website

A Django website consists of a single project that’s split into separate apps. The idea is that each app handles a self-contained task that the site needs to perform. As an example, imagine an application like Instagram. There are several different tasks that it needs to perform:

  • User management: Logging in and out, registering, and so on
  • The image feed: Uploading, editing, and displaying images
  • Private messaging: Sending messages between users and providing notifications

These are each separate pieces of functionality, so if this example were a Django site, then each piece of functionality would be a different Django app inside a single Django project.

Note: A Django project contains at least one app. But even when there are more apps in the Django project, you commonly refer to a Django project as a web app.

The Django project holds some configurations that apply to the project as a whole, such as project settings, URLs, shared templates and static files. Each application can have its own database, and it’ll have its own functions to control how it displays data to the user in HTML templates.

Each application also has its own URLs as well as its own HTML templates and static files, such as JavaScript and CSS.

Django apps are structured so that there’s a separation of logic. It supports the model-view-controller pattern, which is the architecture for most web frameworks. The basic principle is that each application includes three separate files that handle the three main pieces of logic separately:

  • Model defines the data structure. This is usually the database description and often the base layer to an application.
  • View displays some or all of the data to the user with HTML and CSS.
  • Controller handles how the database and the view interact.

If you want to learn more about the MVC pattern, then check out Model-View-Controller (MVC) Explained – With Legos.

Read the full article at https://realpython.com/get-started-with-django-1/ »


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

January 18, 2025 02:00 PM UTC

Python's min() and max(): Find Smallest and Largest Values

Python’s built-in functions max() and min() allow you to find the largest and smallest values in a dataset. You can use them with iterables, such as lists or tuples, or a series of regular arguments. They can handle numbers, strings, and even dictionaries. Plus, with the optional arguments key and default, you can customize their behavior to suit your needs.

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

  • Python’s max() and min() can find the largest and smallest values in a dataset.
  • min() and max() can handle string inputs by comparing their alphabetical order.
  • The key argument modifies comparison criteria by applying a function to each element before comparison.
  • You can use min() and max() with generator expressions for memory-efficient value comparison.

This tutorial explores the practical use cases for min() and max(), such as removing outliers from lists and processing strings. By the end, you’ll also know how to implement your own versions of min() and max() to deepen your understanding of these functions.

Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.

To get the most out of this tutorial, you should have some previous knowledge of Python programming, including topics like for loops, functions, list comprehensions, and generator expressions.

Getting Started With Python’s min() and max() Functions

Python includes several built-in functions that make your life more pleasant and productive because they mean you don’t need to reinvent the wheel. Two examples of these functions are min() and max(). They mostly apply to iterables, but you can use them with multiple regular arguments as well. What’s their job? They take care of finding the smallest and largest values in their input data.

Whether you’re using Python’s min() or max(), you can use the function to achieve two slightly different behaviors. The standard behavior for each is to return the minimum or maximum value through straightforward comparison of the input data as it stands. The alternative behavior is to use a single-argument function to modify the comparison criteria before finding the smallest and largest values.

To explore the standard behavior of min() and max(), you can start by calling each function with either a single iterable as an argument or with two or more regular arguments. That’s what you’ll do right away.

Calling min() and max() With a Single Iterable Argument

The built-in min() and max() have two different signatures that allow you to call them either with an iterable as their first argument or with two or more regular arguments. The signature that accepts a single iterable argument looks something like this:

Python
min(iterable, *[, default, key]) -> minimum_value

max(iterable, *[, default, key]) -> maximum_value
Copied!

Both functions take a required argument called iterable and return the minimum and maximum values respectively. They also take two optional keyword-only arguments: default and key.

Note: In the above signatures, the asterisk (*) means that the following arguments are keyword-only arguments, while the square brackets ([]) denote that the enclosed content is optional.

Here’s a summary of what the arguments to min() and max() do:

Argument Description Required
iterable Takes an iterable object, like a list, tuple, dictionary, or string Yes
default Holds a value to return if the input iterable is empty No
key Accepts a single-argument function to customize the comparison criteria No

Later in this tutorial, you’ll learn more about the optional default and key arguments. For now, just focus on the iterable argument, which is a required argument that leverages the standard behavior of min() and max() in Python:

Python
>>> min([3, 5, 9, 1, -5])
-5

>>> min([])
Traceback (most recent call last):
    ...
ValueError: min() arg is an empty sequence

>>> max([3, 5, 9, 1, -5])
9

>>> max([])
Traceback (most recent call last):
    ...
ValueError: max() arg is an empty sequence
Copied!

In these examples, you call min() and max() with a list of integer numbers and then with an empty list. The first call to min() returns the smallest number in the input list, -5. In contrast, the first call to max() returns the largest number in the list, or 9. If you pass an empty iterator to min() or max(), then you get a ValueError because there’s nothing to do on an empty iterable.

An important detail to note about min() and max() is that all the values in the input iterable must be comparable. Otherwise, you get an error. For example, numeric values work okay:

Python
>>> min([3, 5.0, 9, 1.0, -5])
-5

>>> max([3, 5.0, 9, 1.0, -5])
9
Copied!

These examples combine int and float numbers in the calls to min() and max(). You get the expected result in both cases because these data types are comparable.

However, what would happen if you mixed strings and numbers? Check out the following examples:

Python
>>> min([3, "5.0", 9, 1.0, "-5"])
Traceback (most recent call last):
    ...
TypeError: '<' not supported between instances of 'str' and 'int'

>>> max([3, "5.0", 9, 1.0, "-5"])
Traceback (most recent call last):
    ...
TypeError: '>' not supported between instances of 'str' and 'int'
Copied!

Read the full article at https://realpython.com/python-min-and-max/ »


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

January 18, 2025 02:00 PM UTC


Kushal Das

Dealing with egl_bad_alloc error for webkit

I was trying out some Toga examples, and for the webview I kept getting the following error and a blank screen.

Could not create EGL surfaceless context: EGL_BAD_ALLOC.

After many hours of searching I reduced the reproducer to a simple Python Gtk code.

import gi

gi.require_version('Gtk', '3.0')
gi.require_version('WebKit2', '4.0')

from gi.repository import Gtk, WebKit2

window = Gtk.Window()
window.set_default_size(800, 600)
window.connect("destroy", Gtk.main_quit)

scrolled_window = Gtk.ScrolledWindow()
webview = WebKit2.WebView()
webview.load_uri("https://getfedora.org")
scrolled_window.add(webview)

window.add(scrolled_window)
window.show_all()
Gtk.main()

Finally I asked for help in #fedora IRC channel, within seconds Khaytsus gave me the fix:

WEBKIT_DISABLE_COMPOSITING_MODE=1 python g.py

working webview

January 18, 2025 07:43 AM UTC