os module provides a portable way to interact with the operating system, including file operations, process management, and environment variables.
Module Import
import os
File and Directory Operations
Current Directory
import os
# Get current working directory
cwd = os.getcwd()
print(cwd) # '/home/user/project'
# Change directory
os.chdir('/tmp')
# Create directory
os.mkdir('new_folder')
os.makedirs('path/to/nested/folder') # Create nested directories
# Remove directory
os.rmdir('empty_folder') # Only removes empty directories
os.removedirs('path/to/folder') # Remove nested empty directories
Listing Directory Contents
import os
# List all files and directories
contents = os.listdir('.')
print(contents) # ['file1.txt', 'folder1', 'file2.py']
# List with full paths
for item in os.listdir('/path/to/dir'):
full_path = os.path.join('/path/to/dir', item)
print(full_path)
# Filter for specific files
python_files = [f for f in os.listdir('.') if f.endswith('.py')]
os.scandir() - Efficient Directory Iteration
import os
# More efficient than listdir for detailed info
with os.scandir('.') as entries:
for entry in entries:
if entry.is_file():
print(f"File: {entry.name} ({entry.stat().st_size} bytes)")
elif entry.is_dir():
print(f"Directory: {entry.name}")
os.walk() - Recursive Directory Traversal
import os
# Walk through directory tree
for dirpath, dirnames, filenames in os.walk('.'):
print(f"Current directory: {dirpath}")
print(f"Subdirectories: {dirnames}")
print(f"Files: {filenames}")
print()
# Find all Python files recursively
for dirpath, _, filenames in os.walk('.'):
for filename in filenames:
if filename.endswith('.py'):
full_path = os.path.join(dirpath, filename)
print(full_path)
File Operations
Creating and Removing Files
import os
# Remove file
os.remove('file.txt')
os.unlink('file.txt') # Alias for remove
# Rename/move file
os.rename('old_name.txt', 'new_name.txt')
os.replace('source.txt', 'dest.txt') # Atomic replacement
File Information
import os
from datetime import datetime
# Get file stats
stats = os.stat('file.txt')
print(f"Size: {stats.st_size} bytes")
print(f"Modified: {datetime.fromtimestamp(stats.st_mtime)}")
print(f"Created: {datetime.fromtimestamp(stats.st_ctime)}")
print(f"Accessed: {datetime.fromtimestamp(stats.st_atime)}")
# Check if path exists
if os.path.exists('file.txt'):
print("File exists")
# Check if it's a file or directory
if os.path.isfile('file.txt'):
print("It's a file")
if os.path.isdir('folder'):
print("It's a directory")
if os.path.islink('symlink'):
print("It's a symbolic link")
Path Manipulation (os.path)
Joining Paths
import os
# Join path components (cross-platform)
path = os.path.join('folder', 'subfolder', 'file.txt')
print(path) # 'folder/subfolder/file.txt' on Unix
# 'folder\\subfolder\\file.txt' on Windows
# Build absolute path
abs_path = os.path.join(os.getcwd(), 'data', 'file.txt')
Path Components
import os
path = '/home/user/documents/file.txt'
# Split into directory and filename
dir_name, file_name = os.path.split(path)
print(dir_name) # '/home/user/documents'
print(file_name) # 'file.txt'
# Get directory name
dir_name = os.path.dirname(path)
print(dir_name) # '/home/user/documents'
# Get filename
file_name = os.path.basename(path)
print(file_name) # 'file.txt'
# Split extension
name, ext = os.path.splitext('file.txt')
print(name) # 'file'
print(ext) # '.txt'
Path Properties
import os
path = '/home/user/file.txt'
# Get absolute path
abs_path = os.path.abspath(path)
# Resolve relative path
real_path = os.path.realpath(path) # Follows symlinks
# Expand user home directory
expanded = os.path.expanduser('~/documents')
print(expanded) # '/home/user/documents'
# Check if path is absolute
if os.path.isabs(path):
print("Absolute path")
Environment Variables
os.environ
Dictionary of environment variables.import os
# Get environment variable
path = os.environ.get('PATH')
home = os.environ.get('HOME')
user = os.environ.get('USER', 'unknown') # Default value
# Set environment variable
os.environ['MY_VAR'] = 'value'
# Delete environment variable
del os.environ['MY_VAR']
# Iterate over all variables
for key, value in os.environ.items():
print(f"{key} = {value}")
os.getenv() and os.putenv()
import os
# Get environment variable
value = os.getenv('PATH')
value = os.getenv('CUSTOM_VAR', 'default') # With default
# Set environment variable (prefer os.environ)
os.putenv('MY_VAR', 'value')
Process Management
Current Process
import os
# Get process ID
pid = os.getpid()
print(f"Current PID: {pid}")
# Get parent process ID
ppid = os.getppid()
print(f"Parent PID: {ppid}")
Running Commands
import os
# Execute command (deprecated, use subprocess instead)
os.system('ls -la')
# Get command output (use subprocess.run instead)
# output = os.popen('ls').read()
# Better approach:
import subprocess
result = subprocess.run(['ls', '-la'], capture_output=True, text=True)
print(result.stdout)
File Descriptors
Low-Level File Operations
import os
# Open file (returns file descriptor)
fd = os.open('file.txt', os.O_RDWR | os.O_CREAT)
# Read from file descriptor
data = os.read(fd, 1024) # Read up to 1024 bytes
# Write to file descriptor
os.write(fd, b'Hello, World!')
# Close file descriptor
os.close(fd)
File Descriptor Operations
import os
# Duplicate file descriptor
fd2 = os.dup(fd)
# Change file position
os.lseek(fd, 0, os.SEEK_SET) # Beginning
os.lseek(fd, 0, os.SEEK_END) # End
os.lseek(fd, 10, os.SEEK_CUR) # Current + 10
Permissions and Ownership
File Permissions
import os
import stat
# Change file permissions
os.chmod('file.txt', 0o644) # rw-r--r--
os.chmod('script.sh', 0o755) # rwxr-xr-x
# Using stat constants
os.chmod('file.txt', stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
# Check permissions
stats = os.stat('file.txt')
mode = stats.st_mode
if mode & stat.S_IXUSR:
print("File is executable by owner")
Ownership (Unix only)
import os
# Change owner (requires privileges)
os.chown('file.txt', uid, gid)
Platform-Specific
Path Separators
import os
print(os.sep) # '/' on Unix, '\\' on Windows
print(os.pathsep) # ':' on Unix, ';' on Windows
print(os.linesep) # '\n' on Unix, '\r\n' on Windows
# Platform name
print(os.name) # 'posix', 'nt', 'java'
Special Paths
import os
print(os.devnull) # '/dev/null' on Unix, 'nul' on Windows
print(os.curdir) # '.'
print(os.pardir) # '..'
Practical Examples
Find All Files with Extension
import os
def find_files(directory, extension):
"""Find all files with given extension recursively"""
matches = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(extension):
matches.append(os.path.join(root, file))
return matches
# Usage
python_files = find_files('.', '.py')
for file in python_files:
print(file)
Get Directory Size
import os
def get_directory_size(directory):
"""Calculate total size of directory in bytes"""
total_size = 0
for dirpath, dirnames, filenames in os.walk(directory):
for filename in filenames:
filepath = os.path.join(dirpath, filename)
if os.path.isfile(filepath):
total_size += os.path.getsize(filepath)
return total_size
# Usage
size = get_directory_size('.')
print(f"Directory size: {size / (1024**2):.2f} MB")
Create Backup with Timestamp
import os
from datetime import datetime
import shutil
def backup_file(filepath):
"""Create timestamped backup of file"""
if not os.path.exists(filepath):
return None
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
name, ext = os.path.splitext(filepath)
backup_path = f"{name}_{timestamp}{ext}"
shutil.copy2(filepath, backup_path)
return backup_path
# Usage
backup = backup_file('important.txt')
print(f"Backup created: {backup}")
Safe File Operations
import os
import tempfile
def safe_write(filepath, content):
"""Write to file atomically using temp file"""
# Get directory and create temp file in same location
directory = os.path.dirname(filepath) or '.'
# Write to temporary file
fd, temp_path = tempfile.mkstemp(dir=directory, text=True)
try:
with os.fdopen(fd, 'w') as f:
f.write(content)
# Atomic replacement
os.replace(temp_path, filepath)
except:
# Clean up temp file on error
if os.path.exists(temp_path):
os.remove(temp_path)
raise
# Usage
safe_write('config.txt', 'new configuration')
Best Practices
Use pathlib for modern path handling:
For new code, consider using
pathlib.Path instead of os.path:from pathlib import Path
path = Path('folder') / 'subfolder' / 'file.txt'
if path.exists():
content = path.read_text()
Be careful with os.remove():
It permanently deletes files without moving them to trash. Always verify the path before removing.
if os.path.exists(filepath) and os.path.isfile(filepath):
os.remove(filepath)
Use os.path.join() for cross-platform paths:
Always use
os.path.join() instead of string concatenation with / or \\.# Good
path = os.path.join('folder', 'file.txt')
# Bad
path = 'folder' + '/' + 'file.txt'
Migration to pathlib
Manyos and os.path functions have pathlib equivalents:
import os
from pathlib import Path
# os module → pathlib
os.getcwd() # Path.cwd()
os.path.exists(path) # Path(path).exists()
os.path.isfile(path) # Path(path).is_file()
os.path.isdir(path) # Path(path).is_dir()
os.listdir(path) # list(Path(path).iterdir())
os.mkdir(path) # Path(path).mkdir()
os.rename(old, new) # Path(old).rename(new)
os.remove(path) # Path(path).unlink()
os.rmdir(path) # Path(path).rmdir()
Related Modules
pathlib
Object-oriented filesystem paths
shutil
High-level file operations
glob
Unix-style pathname pattern expansion
tempfile
Temporary files and directories
