Mathew K Analytics

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…

⬇ Download notebookOpen in Colab ↗

📓 Full notebook

Download .ipynb

Python 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))
reports\summary.csv
<class 'pathlib.WindowsPath'>
True

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)
c:\PythonTraining\Full_videos\Notebooks
C:\Users\makmw
data\reports\summary.csv
<class 'pathlib.WindowsPath'>
data\reports\summary.csv

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)
summary.final.csv
summary.final
.csv
['.final', '.csv']
\home\user\reports
\home\user
[WindowsPath('/home/user/reports'), WindowsPath('/home/user'), WindowsPath('/home'), WindowsPath('/')]
('\\', 'home', 'user', 'reports', 'summary.final.csv')

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())
True
True
False
False
False
False

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())
Hello from pathlib!
['Line one', 'Line two', 'Line three']
b'\x00\x01\x02'
with note.open('a') as f:
    f.write('\nAppended line')
print(note.read_text())
Line one
Line two
Line three
Appended line

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)
True
True
True
0
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}')
False
False
Caught: [WinError 145] The directory is not empty: 'demo_pathlib_dir'

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)
demo_pathlib_files\archive.csv
demo_pathlib_files\nested
demo_pathlib_files\notes.txt
demo_pathlib_files\report.csv
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))
[WindowsPath('demo_pathlib_files/archive.csv'), WindowsPath('demo_pathlib_files/report.csv')]
[WindowsPath('demo_pathlib_files/archive.csv'), WindowsPath('demo_pathlib_files/nested/deep.csv'), WindowsPath('demo_pathlib_files/report.csv')]
2 3

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()))
C:\PythonTraining\Full_videos\Notebooks\demo_pathlib_files\report.csv
c:\PythonTraining\Full_videos\Notebooks\demo_pathlib_files\report.csv
C:\PythonTraining\Full_videos\Notebooks\demo_pathlib_files\report.csv
demo_pathlib_files\report.csv

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))
demo_pathlib_files\notes_renamed.txt
True
False
5
<class 'float'>

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)
reports\summary.xlsx
reports\archive.csv
reports\summary_backup.csv
reports\summary.csv\nested\deeper.csv
reports\summary.csv

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))
5
data\file.csv
<class 'pathlib.WindowsPath'>
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')
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.