Lesson 2 · Python standard library deep dive
Python pathlib Explained: Modern File Paths Made Easy | Standard Library #2
Video two of the twenty-five-part series: pathlib, the modern, object-oriented replacement for os.path. Building paths, inspecting their pieces, reading and…
- CoursePython standard library deep dive
- Lesson2 of 24
- Video20 min
- FormatJupyter notebook · 15 code cells
What you'll learn
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynbPython Standard Library Deep-Dive, Video 2: pathlib#
- Video two of the twenty-five-part series: pathlib, the modern, object-oriented replacement for os.path.
- Building paths, inspecting their pieces, reading and writing files, and searching directory trees.
- Let's get into it.
Part 1: What Makes pathlib Different#
from pathlib import Path
p = Path('reports/summary.csv')
print(p)
print(type(p))
print(isinstance(p, Path))
Part 2: Creating Path Objects#
print(Path.cwd())
print(Path.home())
joined = Path('data') / 'reports' / 'summary.csv'
print(joined)
print(type(joined))
base = Path('data')
full = base / 'reports' / 'summary.csv'
print(full)
Part 3: Path Components: name, stem, suffix, parent, parts#
p = Path('/home/user/reports/summary.final.csv')
print(p.name)
print(p.stem)
print(p.suffix)
print(p.suffixes)
print(p.parent)
print(p.parent.parent)
print(list(p.parents))
print(p.parts)
Part 4: Checking Existence and Type#
current = Path.cwd()
print(current.exists())
print(current.is_dir())
print(current.is_file())
missing = Path('genuinely_does_not_exist.txt')
print(missing.exists())
print(Path('/etc').is_absolute())
print(Path('relative/path').is_absolute())
Part 5: Reading and Writing Files#
note = Path('quick_note.txt')
note.write_text('Hello from pathlib!')
print(note.read_text())
note.write_text('Line one\nLine two\nLine three')
print(note.read_text().splitlines())
data_file = Path('quick_data.bin')
data_file.write_bytes(b'\x00\x01\x02')
print(data_file.read_bytes())
with note.open('a') as f:
f.write('\nAppended line')
print(note.read_text())
Part 6: Creating and Removing: mkdir, rmdir, unlink, touch#
new_dir = Path('demo_pathlib_dir')
new_dir.mkdir(exist_ok=True)
print(new_dir.is_dir())
nested = Path('demo_pathlib_dir/a/b/c')
nested.mkdir(parents=True, exist_ok=True)
print(nested.is_dir())
empty_file = Path('demo_pathlib_dir/placeholder.txt')
empty_file.touch()
print(empty_file.exists())
print(empty_file.stat().st_size)
empty_file.unlink()
print(empty_file.exists())
Path('demo_pathlib_dir/a/b/c').rmdir()
print(Path('demo_pathlib_dir/a/b/c').exists())
try:
Path('demo_pathlib_dir').rmdir()
except OSError as e:
print(f'Caught: {e}')
Part 7: Listing and Globbing: iterdir, glob, rglob#
demo = Path('demo_pathlib_files')
demo.mkdir(exist_ok=True)
(demo / 'report.csv').write_text('a,b,c')
(demo / 'notes.txt').write_text('notes')
(demo / 'archive.csv').write_text('x,y,z')
sub = demo / 'nested'
sub.mkdir(exist_ok=True)
(sub / 'deep.csv').write_text('deep')
for item in demo.iterdir():
print(item)
csv_files = list(demo.glob('*.csv'))
print(sorted(csv_files))
all_csv_files = list(demo.rglob('*.csv'))
print(sorted(all_csv_files))
print(len(csv_files), len(all_csv_files))
Part 8: Resolving Paths: resolve, absolute, relative_to#
relative = Path('demo_pathlib_files/report.csv')
print(relative.resolve())
print(relative.absolute())
messy = Path('demo_pathlib_files/../demo_pathlib_files/report.csv')
print(messy.resolve())
full = Path.cwd() / 'demo_pathlib_files' / 'report.csv'
print(full.relative_to(Path.cwd()))
Part 9: Renaming and stat()#
original = Path('demo_pathlib_files/notes.txt')
renamed = original.rename('demo_pathlib_files/notes_renamed.txt')
print(renamed)
print(renamed.exists())
print(original.exists())
info = renamed.stat()
print(info.st_size)
print(type(info.st_mtime))
Part 10: with_name(), with_suffix(), with_stem(), joinpath()#
original = Path('reports/summary.csv')
print(original.with_suffix('.xlsx'))
print(original.with_name('archive.csv'))
print(original.with_stem('summary_backup'))
print(original.joinpath('nested', 'deeper.csv'))
print(original)
Part 11: pathlib vs os.path#
import os
p = Path('demo_pathlib_files/report.csv')
print(os.path.getsize(str(p)))
from_string = Path(os.path.join('data', 'file.csv'))
print(from_string)
print(type(from_string))
import shutil
shutil.rmtree('demo_pathlib_dir')
shutil.rmtree('demo_pathlib_files')
Path('quick_note.txt').unlink()
Path('quick_data.bin').unlink()
print('cleanup complete')
Wrap-Up: What You Learned#
- pathlib treats paths as objects, not strings, and has been the recommended approach since Python 3.4.
- Construction with Path(), cwd(), home(), and the slash operator.
- Components: name, stem, suffix, suffixes, parent, parents, parts.
- Existence checks, reading and writing with read_text/write_text/read_bytes/write_bytes, and Path.open for everything else.
- Creating and removing with mkdir, rmdir, unlink, touch.
- Searching with iterdir, glob, and rglob; resolving with resolve, absolute, relative_to.
- Renaming, stat(), and building new paths non-destructively with with_suffix, with_name, with_stem, joinpath.
- That wraps up pathlib. Next up: datetime, for dates, times, and timezones.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



