Skip to content

Python pathlib — Modern File Paths

pathlib provides an object-oriented way to work with filesystem paths. Instead of juggling strings and os.path.join, you use a Path object with clean attributes and methods that work the same on Windows, macOS, and Linux.

quickstart.py
from pathlib import Path
 
p = Path("data") / "reports" / "2025.csv"   # join with the / operator
print(p)            # data/reports/2025.csv  (uses the OS separator)
print(p.name)       # 2025.csv
print(p.suffix)     # .csv
print(p.parent)     # data/reports
os.path (old)pathlib (modern)
os.path.join(a, b)Path(a) / b
os.path.basename(p)p.name
os.path.splitext(p)[1]p.suffix
os.path.exists(p)p.exists()
Strings everywhere.One tidy object.

Use the / operator to join parts — it’s readable and cross-platform.

building.py
from pathlib import Path
 
base = Path("/home/user")
config = base / "app" / "config.json"
print(config)                 # /home/user/app/config.json
 
# Current working directory and home directory
print(Path.cwd())             # where the script runs
print(Path.home())            # the user's home folder
Attribute / methodReturns
p.nameFinal component (2025.csv).
p.stemName without suffix (2025).
p.suffixThe extension (.csv).
p.parentThe containing directory.
p.partsA tuple of all components.
p.with_suffix(".txt")A new path with a changed extension.
p.with_name("new.csv")A new path with a changed final name.
inspecting.py
from pathlib import Path
 
p = Path("reports/q1/sales.csv")
print(p.name)               # sales.csv
print(p.stem)               # sales
print(p.suffix)             # .csv
print(p.parent)             # reports/q1
print(p.parts)              # ('reports', 'q1', 'sales.csv')
print(p.with_suffix(".json"))  # reports/q1/sales.json
sketch pathlib knows about extensions; os.path.splitext does not p5.js
A path is not a string, and the difference shows up on the parts people actually want. For file.tar.gz, pathlib gives the suffix, the stem and the full list of suffixes, while os.path.splitext strips exactly one extension and calls the rest the name. pathlib also costs more -- about three times os.path.join per operation -- because it builds an object rather than concatenating text. At two microseconds per call that only matters in a loop over very many paths.
checks.py
from pathlib import Path
 
p = Path("notes.txt")
print(p.exists())     # True if the path exists
print(p.is_file())    # True if it's a file
print(p.is_dir())     # True if it's a directory

pathlib can read and write whole files in one line — no open() boilerplate for simple cases.

read_write.py
from pathlib import Path
 
p = Path("greeting.txt")
p.write_text("Hello, file!", encoding="utf-8")   # write (and create)
print(p.read_text(encoding="utf-8"))              # Hello, file!
 
# Binary variants
p.write_bytes(b"\x00\x01")
print(p.read_bytes())                             # b'\x00\x01'
listing.py
from pathlib import Path
 
folder = Path(".")
 
# Everything directly inside
for item in folder.iterdir():
    print(item)
 
# Only .py files in this folder
for py in folder.glob("*.py"):
    print(py)
 
# Recursively, every .py file under here
for py in folder.rglob("*.py"):
    print(py)
MethodFinds
p.iterdir()Every item directly inside p.
p.glob(pattern)Items matching a pattern in p.
p.rglob(pattern)Matches recursively in all subfolders.
create_remove.py
from pathlib import Path
 
d = Path("output/logs")
d.mkdir(parents=True, exist_ok=True)   # create folders; don't error if present
 
f = d / "run.log"
f.touch()                              # create an empty file
f.unlink(missing_ok=True)             # delete a file (no error if missing)
  • Path("a") / "b" only works with a Path on the left"a" / Path("b") fails; start from a Path.
  • p.suffix includes the dot.csv, not csv.
  • mkdir errors if the parent is missing — pass parents=True.
  • read_text raises if the file doesn’t exist — check p.exists() first or catch the error.
  • Convert to str(p) only when a library insists on a string.

Exercise 2 – Join paths with the / operator

Section titled “Exercise 2 – Join paths with the / operator”
  • pathlib.Path is the modern, object-oriented replacement for os.path.
  • Join paths with /; inspect them with name, stem, suffix, parent, parts.
  • Read/write files directly with read_text/write_text (and _bytes variants).
  • List and search folders with iterdir, glob, and rglob.
  • Create and remove with mkdir(parents=True, exist_ok=True), touch, and unlink.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading