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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Use ALL_CAPS names for module-level constants. 🧵
MAX_RETRIES = 5
DEFAULT_TIMEOUT = 30
pym.dev/python-doesn...
#Python #DailyPythonTip
Use ALL_CAPS names for module-level constants. 🧵
MAX_RETRIES = 5
DEFAULT_TIMEOUT = 30
pym.dev/python-doesn...
#Python #DailyPythonTip
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
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
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
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
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
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
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
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
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
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
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
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