#DailyPythonTip
Python Tip #269 (of 365):

Walk directory trees with Path.walk. 🧵

The walk method (Python 3.12+) is the pathlib version of os.walk. For each directory in the tree, you get the directory's path, a list of its subdirectory names, and a list of its file names.

#Python #DailyPythonTip
September 26, 2026 at 10:52 PM
Python Tip #268 (of 365):

Show relative paths with relative_to. 🧵

Absolute paths are noisy:

>>> print(path)
/home/trey/taxes/archived/2017/invoices
>>> taxes
PosixPath('/home/trey/taxes')
>>> print(path.relative_to(taxes))
archived/2017/invoices

#Python #DailyPythonTip
September 26, 2026 at 4:30 AM
Python Tip #267 (of 365):

Change file extensions with with_suffix. 🧵

A ".rst" file path that needs to turn into a ".md" file path:

>>> from pathlib import Path
>>> old_path = Path("uvrs/readme.rst")
>>> old_path.with_suffix(".md")
PosixPath('uvrs/readme.md')

#Python #DailyPythonTip
September 24, 2026 at 5:02 PM
Python Tip #266 (of 365):

Reread a file with seek(0). 🧵

Try to .read() a file twice, and you'll get nothing the second time:

>>> f = open("my_file.txt")
>>> f‍.read()
'This is my file 👋\nThis is line 2\n'
>>> f‍.read()
''

#Python #DailyPythonTip
September 23, 2026 at 5:02 PM
Python Tip #265 (of 365):

Use next() to get the first line in a file. 🧵

#Python #DailyPythonTip
September 22, 2026 at 5:02 PM
Python Tip #264 (of 365):

Don't use the file readlines method. 🧵

Do this:
lines = list(file)

Not this:
lines = file.readlines()

Both give the same list of lines. So why prefer list?

#Python #DailyPythonTip
September 21, 2026 at 5:01 PM
Python Tip #263 (of 365):

Parse messy dates with the third-party dateutil library. 🧵

>>> from dateutil.parser import parse
>>> parse("September 20, 2026")
datetime.datetime(2026, 9, 20, 0, 0)
>>> parse("20 Sep 2026 14:30")
datetime.datetime(2026, 9, 20, 14, 30)

#Python #DailyPythonTip
September 20, 2026 at 6:04 PM
Python Tip #262 (of 365):

Parse dates with date.strptime. 🧵

In Python 3.14+, the date class got its own strptime class method:

>>> import datetime as dt
>>> dt.date.strptime("2026-08-19", "%Y-%m-%d")
datetime‍.date(2026, 8, 19)

#Python #DailyPythonTip
September 19, 2026 at 5:00 PM
Python Tip #261 (of 365):

Use Python's zoneinfo module when working with time zones. 🧵

>>> from zoneinfo import ZoneInfo
>>> pacific = ZoneInfo("America/Los_Angeles")
>>> meeting = datetime(2027, 3, 13, 9, 0, tzinfo=pacific)
>>> print(meeting)
2027-03-13 09:00:00-08:00

#Python #DailyPythonTip
September 18, 2026 at 5:01 PM
Python Tip #260 (of 365):

Bookmark a date format cheat sheet. 🧵

Is "%M" month or minute? Is "%H" 12 or 24 hour time? Which one shows a long month name? And a short one?

You COULD memorize all of Python's many date/time format codes, but is that worth it?

#Python #DailyPythonTip
September 17, 2026 at 8:16 PM
Python Tip #259 (of 365):

Use datetime arithmetic and comparisons to check if a date is within a range. 🧵

Sputnik launched before the moon landing:

>>> sputnik_launch = datetime(1957, 10, 4)
>>> moon_landing = datetime(1969, 7, 20)
>>> sputnik_launch < moon_landing
True

#Python #DailyPythonTip
September 17, 2026 at 2:12 AM
Python Tip #258 (of 365):

Format dates with f-strings. 🧵

datetime objects support the same format codes in f-string format specifiers that the strftime method uses:

>>> deadline = datetime(2046, 10, 31, 15, 46)
>>> f"{deadline:%m/%d/%Y %I:%M %p}"
'10/31/2046 03:46 PM'

#Python #DailyPythonTip
September 15, 2026 at 5:01 PM
Python Tip #257 (of 365):

Consider "import datetime as dt". 🧵

The fact that the datetime module and the datetime class are spelled the same way is VERY confusing.

#Python #DailyPythonTip
September 14, 2026 at 7:27 PM
Python Tip #256 (of 365):

Avoid circular imports by decoupling your modules. 🧵

Two modules that import each other will break.

In users.models:
from .tasks import send_welcome_email

And in users.tasks:
from .models import User

#Python #DailyPythonTip
September 14, 2026 at 2:24 AM
Python Tip #255 (of 365):

Declare your public API with __all__. 🧵

from math import sqrt

__all__ = ["nth_lucas", "sum_of_squares"]

phi = (1+sqrt(5))/2

def nth_lucas(n):
return round(phi**n + (-1/phi)**n)

def sum_of_squares(*nums):
return sum(n**2 for n in nums)

#Python #DailyPythonTip
September 12, 2026 at 11:03 PM
Python Tip #254 (of 365):

Use a module instead of a singleton class. 🧵

When you import a module, Python creates a module object. Import it again and you get THE EXACT SAME OBJECT:

>>> import events
>>> import events as again
>>> again is events
True

#Python #DailyPythonTip
September 12, 2026 at 4:35 AM
Python Tip #253 (of 365):

Avoid import side effects in your Python modules. 🧵

The top level of a module should only DEFINE things: functions, classes, constants, and other objects meant to be accessed after import. Don't print, prompt for input, write to files, etc.

#Python #DailyPythonTip
September 10, 2026 at 6:04 PM
Python Tip #252 (of 365):

Use ALL_CAPS names for module-level constants. 🧵

MAX_RETRIES = 5
DEFAULT_TIMEOUT = 30

pym.dev/python-doesn...

#Python #DailyPythonTip
September 9, 2026 at 10:52 PM
Python Tip #251 (of 365):

Avoid wildcard imports. 🧵

Using star imports, like "from something import *", makes for fragile code.

The Zen of Python ends with "Namespaces are one honking great idea -- let's do more of those!"

#Python #DailyPythonTip
September 8, 2026 at 6:04 PM
Python Tip #250 (of 365):

Sort your import statements in a meaningful way. 🧵

The usual convention (from PEP 8): standard library first, then third-party packages, then your own code.

import json

from django.http import Http404

from exercises.models import Exercise

#Python #DailyPythonTip
September 8, 2026 at 2:48 AM
Python Tip #249 (of 365):

Monkey patch cautiously... and only in your automated tests. 🧵

Monkey patching means fundamentally changing how a module or class works WITHOUT editing its code, by reassigning one of its attributes at runtime.

In tests, it can simplify things.

#Python #DailyPythonTip
September 7, 2026 at 2:28 AM
Python Tip #248 (of 365):

Run "pytest --pdb" to drop into PDB when a test fails. 🧵

With "--pdb", pytest starts PDB in post-mortem mode (see tip #169) as soon as a test fails or raises an exception.

#Python #DailyPythonTip
Trey Hunner (@trey.io)
Python Tip #169 (of 365): Use PDB's post-mortem mode to debug exceptions 🧵 Python script raising an exception and want to drop into an interactive environment RIGHT after the exception occurs? Use…
bsky.app
September 6, 2026 at 3:23 AM
Python Tip #247 (of 365):

Test file processing code with tempfile. 🧵

These are the 2 most useful tempfile utilities:

• NamedTemporaryFile: makes a file that Python deletes automatically
• TemporaryDirectory: makes a directory that Python deletes automatically

#Python #DailyPythonTip
Creating temporary files in Python
How to create temporary files and directories in Python using the tempfile module's NamedTemporaryFile and TemporaryDirectory.
pym.dev
September 5, 2026 at 12:08 AM
Python Tip #246 (of 365):

Measure your test coverage, including BRANCH coverage. 🧵

$ coverage run --branch -m pytest
$ coverage report

Or with the pytest-cov plugin:
$ pytest --cov --cov-branch

#Python #DailyPythonTip
September 4, 2026 at 3:44 AM