pathlib
from pathlib import Path The pathlib module provides an object-oriented interface for working with filesystem paths. Instead of dealing with raw strings like /home/user/file.txt, you get intuitive objects with methods that make common operations simple. The module separates pure paths (which only manipulate path strings without touching the filesystem) from concrete paths (which can read files, create directories, and check file properties).
If you’re new to pathlib, Path is the class you want. It automatically selects the right path flavor for your operating system. Pure path classes are useful when you need to manipulate paths on different operating systems or when you want path operations without any filesystem access.
Syntax
from pathlib import Path
from pathlib import PurePath, PurePosixPath, PureWindowsPath
Classes
Path
The Path class is the main entry point for most use cases. It represents a concrete path on the current system, automatically choosing between PosixPath (Unix/Linux/macOS) and WindowsPath (Windows) based on where your code runs.
from pathlib import Path
# Create a path object
p = Path('docs/guide.md')
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
*pathsegments | str/PathLike | — | Path components to join together |
Key methods:
| Method | Description |
|---|---|
exists() | Check if path exists |
is_file() | Check if path is a regular file |
is_dir() | Check if path is a directory |
is_symlink() | Check if path is a symbolic link |
read_text() | Read file contents as string |
read_bytes() | Read file contents as bytes |
write_text(data) | Write string to file |
write_bytes(data) | Write bytes to file |
iterdir() | Iterate over directory contents |
glob(pattern) | Find files matching pattern |
rglob(pattern) | Recursive glob search |
walk() | Walk directory tree |
mkdir() | Create directory |
touch() | Create empty file |
unlink() | Delete file |
rmdir() | Delete empty directory |
rename(target) | Rename file or directory |
replace(target) | Replace file atomically |
resolve() | Get absolute path with symlinks resolved |
stat() | Get file statistics |
symlink_to(target) | Create symbolic link |
hardlink_to(target) | Create hard link |
Class methods:
| Method | Description |
|---|---|
cwd() | Return current directory |
home() | Return user home directory |
from_uri(uri) | Create path from file:// URI |
PurePath
PurePath provides the same path manipulation operations as Path but without any filesystem I/O. This is useful when you need to work with paths on different operating systems or when you only need string manipulation.
from pathlib import PurePath, PureWindowsPath
# Works on any OS - creates PurePosixPath or PureWindowsPath
p = PurePath('/usr/local/bin')
# Explicitly create Windows paths
wp = PureWindowsPath('c:/Windows/System32')
Key properties:
| Property | Description |
|---|---|
name | Final path component (filename) |
stem | Name without suffix |
suffix | File extension |
suffixes | Multiple extensions (e.g., .tar.gz) |
parent | Parent directory |
parents | Sequence of all ancestors |
drive | Drive letter or UNC share |
root | Root component (/ or \) |
anchor | Drive + root combined |
parts | Tuple of path components |
Key methods:
| Method | Description |
|---|---|
is_absolute() | Check if path is absolute |
is_relative_to(other) | Check if path is under other |
joinpath(*parts) | Join path segments |
with_name(name) | Replace name component |
with_suffix(suffix) | Replace suffix |
relative_to(other) | Get relative path |
match(pattern) | Match glob pattern |
Examples
Basic path manipulation
from pathlib import Path
# Creating paths with the / operator
base = Path('/home/user')
config = base / 'config' / 'app.ini'
print(config) # /home/user/config/app.ini
# Accessing path components
p = Path('/home/user/documents/report.pdf')
print(p.name) # report.pdf
print(p.stem) # report
print(p.suffix) # .pdf
print(p.suffixes) # ['.pdf']
print(p.parent) # /home/user/documents
print(p.parts) # ('/', 'home', 'user', 'documents', 'report.pdf')
# Changing extensions
new_file = p.with_suffix('.txt')
print(new_file) # /home/user/documents/report.txt
# Changing filename
renamed = p.with_name('summary.pdf')
print(renamed) # /home/user/documents/summary.pdf
Reading and writing files
from pathlib import Path
# Writing and reading text
p = Path('example.txt')
p.write_text('Hello, World!')
content = p.read_text()
print(content) # Hello, World!
# Writing and reading bytes
p = Path('data.bin')
p.write_bytes(b'\x00\x01\x02')
data = p.read_bytes()
print(data) # b'\x00\x01\x02'
# Using context manager for more control
with p.open('w', encoding='utf-8') as f:
f.write('More complex file operations...\n')
f.write('Line 2')
# Reading line by line
with Path('example.txt').open() as f:
for line in f:
print(line.rstrip())
Walking directories
from pathlib import Path
# List directory contents
for item in Path('.').iterdir():
print(item.name)
# Find all Python files
for py_file in Path('.').glob('**/*.py'):
print(py_file)
# Find files directly in current directory
for txt_file in Path('.').glob('*.txt'):
print(txt_file)
# Using walk() to traverse directories
for root, dirs, files in Path('src').walk():
print(f"Directory: {root}")
# Skip hidden directories
dirs[:] = [d for d in dirs if not d.startswith('.')]
# Print file count
print(f" Files: {len(files)}")
Creating and deleting
from pathlib import Path
# Create a directory
Path('new_folder').mkdir(exist_ok=True)
# Create nested directories
Path('project/src/utils').mkdir(parents=True, exist_ok=True)
# Create an empty file
Path('empty.txt').touch()
# Create a symbolic link
Path('link_to_file').symlink_to('original.txt')
# Delete files (careful!)
Path('temp.txt').unlink()
# Delete empty directory
Path('empty_folder').rmdir()
# Copy and move (Python 3.8+)
source = Path('file.txt')
target = Path('backup/file.txt')
source.copy(target) # Copy
source.replace(target) # Move (atomic)
Common Patterns
Path existence checking
from pathlib import Path
p = Path('config.ini')
if p.exists():
print("File exists")
if p.is_file():
print("It's a file")
if p.is_dir():
print("It's a directory")
Safe file operations
from pathlib import Path
# Always resolve paths to handle symlinks
config = Path('config.ini').resolve()
# Use try/except for filesystem errors
try:
content = config.read_text()
except FileNotFoundError:
print("Config file missing, using defaults")
except PermissionError:
print("Cannot read config file")
Cross-platform path handling
from pathlib import Path, PureWindowsPath
# On any OS, work with Windows paths
windows_path = PureWindowsPath('c:/Users/Admin')
print(windows_path / 'Documents')
# Convert between formats
p = Path('/usr/local/bin')
print(p.as_uri()) # file:///usr/local/bin
# Get POSIX representation on Windows
wp = PureWindowsPath('c:/Program Files')
print(wp.as_posix()) # c:/Program Files