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.
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/reportsWhy pathlib over os.path?
Section titled “Why pathlib over os.path?”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. |
Building paths
Section titled “Building paths”Use the / operator to join parts — it’s readable and cross-platform.
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 folderInspecting a path
Section titled “Inspecting a path”| Attribute / method | Returns |
|---|---|
p.name | Final component (2025.csv). |
p.stem | Name without suffix (2025). |
p.suffix | The extension (.csv). |
p.parent | The containing directory. |
p.parts | A 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. |
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.jsonChecking existence and type
Section titled “Checking existence and type”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 directoryReading and writing files
Section titled “Reading and writing files”pathlib can read and write whole files in one line — no open() boilerplate for simple cases.
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 and globbing directories
Section titled “Listing and globbing directories”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)| Method | Finds |
|---|---|
p.iterdir() | Every item directly inside p. |
p.glob(pattern) | Items matching a pattern in p. |
p.rglob(pattern) | Matches recursively in all subfolders. |
Creating and removing
Section titled “Creating and removing”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)Common pitfalls
Section titled “Common pitfalls”Path("a") / "b"only works with a Path on the left —"a" / Path("b")fails; start from aPath.p.suffixincludes the dot —.csv, notcsv.mkdirerrors if the parent is missing — passparents=True.read_textraises if the file doesn’t exist — checkp.exists()first or catch the error.- Convert to
str(p)only when a library insists on a string.
Practice Exercises
Section titled “Practice Exercises”Exercise 1 – Extract the file extension
Section titled “Exercise 1 – Extract the file extension”Exercise 2 – Join paths with the / operator
Section titled “Exercise 2 – Join paths with the / operator”Exercise 3 – Name without the extension
Section titled “Exercise 3 – Name without the extension”Summary
Section titled “Summary”pathlib.Pathis the modern, object-oriented replacement foros.path.- Join paths with
/; inspect them withname,stem,suffix,parent,parts. - Read/write files directly with
read_text/write_text(and_bytesvariants). - List and search folders with
iterdir,glob, andrglob. - Create and remove with
mkdir(parents=True, exist_ok=True),touch, andunlink.
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading