pathlib.PosixPath - POSIX Paths with Filesystem I/O
Class:
pathlib.PosixPath
Inheritance:PurePosixPath→PosixPath
Category: File System Operations
Python Version: 3.4+
Overview
pathlib.PosixPath is a concrete implementation of PurePosixPath that provides actual filesystem I/O operations on POSIX systems (Unix, Linux, macOS). It combines POSIX-style path manipulation with real filesystem operations like reading files, creating directories, and checking file existence. This class is only available on POSIX systems.
📚 Basic Usage
Simple Example
import os
from pathlib import PosixPath
# Note: PosixPath only works on POSIX systems (Unix/Linux/macOS)
if os.name == 'posix':
# Create PosixPath objects with I/O capabilities
home = PosixPath.home()
current = PosixPath.cwd()
config_dir = PosixPath("/etc/myapp")
print(f"Home: {home}") # /home/username or /Users/username
print(f"Current: {current}") # /current/working/directory
print(f"Config: {config_dir}") # /etc/myapp
# File operations with POSIX paths
temp_file = PosixPath("/tmp/test.txt")
# Write and read operations
temp_file.write_text("Hello, POSIX world!")
content = temp_file.read_text()
print(f"Content: {content}")
# Check existence and properties
print(f"Exists: {temp_file.exists()}")
print(f"Is file: {temp_file.is_file()}")
# Clean up
temp_file.unlink()
Core Methods/Functions
import os
from pathlib import PosixPath
if os.name == 'posix':
# Directory operations
data_dir = PosixPath("/tmp/data_processing")
data_dir.mkdir(parents=True, exist_ok=True)
# Create subdirectories
input_dir = data_dir / "input"
output_dir = data_dir / "output"
logs_dir = data_dir / "logs"
for directory in [input_dir, output_dir, logs_dir]:
directory.mkdir(exist_ok=True)
# File operations
config_file = data_dir / "config.yaml"
log_file = logs_dir / "processing.log"
# Write configuration
config_content = """
database:
host: localhost
port: 5432
name: myapp
""".strip()
config_file.write_text(config_content)
# Check permissions and metadata
print(f"Config permissions: {oct(config_file.stat().st_mode)[-3:]}")
print(f"Owner: {config_file.owner()}")
print(f"Group: {config_file.group()}")
# Directory traversal
print("Directory contents:")
for item in data_dir.iterdir():
print(f" {item.name} ({'dir' if item.is_dir() else 'file'})")
Common Patterns
import os
from pathlib import PosixPath
import shutil
if os.name == 'posix':
# Pattern 1: Safe file operations with permissions
def create_secure_config(config_path: PosixPath, content: str):
"""Create configuration file with secure permissions."""
# Create parent directories if needed
config_path.parent.mkdir(parents=True, exist_ok=True, mode=0o755)
# Write file with restricted permissions (600 = rw-------)
config_path.write_text(content)
config_path.chmod(0o600) # Only owner can read/write
return config_path
# Pattern 2: POSIX-specific directory operations
def setup_unix_service_dirs(service_name: str) -> dict:
"""Set up standard Unix service directory structure."""
base_dirs = {
"config": PosixPath(f"/etc/{service_name}"),
"data": PosixPath(f"/var/lib/{service_name}"),
"logs": PosixPath(f"/var/log/{service_name}"),
"run": PosixPath(f"/var/run/{service_name}"),
"cache": PosixPath(f"/var/cache/{service_name}")
}
for dir_type, path in base_dirs.items():
if not path.exists():
print(f"Would create {dir_type} directory: {path}")
# In real usage: path.mkdir(parents=True, mode=0o755)
return base_dirs
# Pattern 3: Unix file permissions management
def secure_file_permissions(file_path: PosixPath):
"""Apply secure permissions to file based on type."""
if file_path.suffix in ['.sh', '.py']:
# Executable scripts: rwxr-xr-x (755)
file_path.chmod(0o755)
elif file_path.suffix in ['.conf', '.yaml', '.json']:
# Configuration files: rw-r--r-- (644)
file_path.chmod(0o644)
elif 'secret' in file_path.name.lower() or 'key' in file_path.name.lower():
# Secret files: rw------- (600)
file_path.chmod(0o600)
else:
# Default files: rw-r--r-- (644)
file_path.chmod(0o644)
# Usage examples
config_path = PosixPath("/tmp/app_config.yaml")
create_secure_config(config_path, "secret_key: abc123")
service_dirs = setup_unix_service_dirs("webapp")
for dir_type, path in service_dirs.items():
print(f"{dir_type}: {path}")
🔧 PosixPath API Reference
Inherited from Path (Filesystem I/O)
All methods from pathlib.Path are available with POSIX-specific behavior:
| Method | POSIX-Specific Notes | Example |
|---|---|---|
exists() | Uses POSIX filesystem calls | path.exists() |
is_file() | POSIX file type checking | path.is_file() |
is_dir() | POSIX directory checking | path.is_dir() |
is_symlink() | POSIX symbolic link detection | path.is_symlink() |
stat() | Returns POSIX stat structure | path.stat() |
chmod() | POSIX permission setting | path.chmod(0o755) |
owner() | POSIX user name | path.owner() |
group() | POSIX group name | path.group() |
POSIX-Specific Extensions
| Method | Description | Parameters | Return Type | Example |
|---|---|---|---|---|
chmod() | Set POSIX permissions | mode: int | None | path.chmod(0o755) |
owner() | Get file owner name | None | str | path.owner() |
group() | Get file group name | None | str | path.group() |
is_mount() | Check if mount point | None | bool | path.is_mount() |
is_socket() | Check if Unix socket | None | bool | path.is_socket() |
is_fifo() | Check if named pipe | None | bool | path.is_fifo() |
is_block_device() | Check if block device | None | bool | path.is_block_device() |
is_char_device() | Check if character device | None | bool | path.is_char_device() |
POSIX Permission Constants
Common POSIX permission values for use with chmod():
| Permission | Octal | Description | Use Case |
|---|---|---|---|
0o755 | 755 | rwxr-xr-x | Executable files, directories |
0o644 | 644 | rw-r--r-- | Regular files, configuration |
0o600 | 600 | rw------- | Private files, secrets |
0o700 | 700 | rwx------ | Private directories |
0o444 | 444 | r--r--r-- | Read-only files |
0o777 | 777 | rwxrwxrwx | World-writable (generally avoid) |
🐛 Common Errors and Troubleshooting
Typical Error Messages
import os
from pathlib import PosixPath
if os.name == 'posix':
# Error 1: Permission denied
try:
restricted_file = PosixPath("/root/.bashrc")
content = restricted_file.read_text()
except PermissionError as e:
print(f"Permission denied: {e}")
# Solution: Run with appropriate privileges or check permissions
print(f"File permissions: {oct(restricted_file.stat().st_mode)[-3:]}")
# Error 2: File not found in POSIX filesystem
try:
nonexistent = PosixPath("/nonexistent/path/file.txt")
nonexistent.read_text()
except FileNotFoundError as e:
print(f"File not found: {e}")
# Solution: Check path exists and is accessible
print(f"Parent exists: {nonexistent.parent.exists()}")
# Error 3: Device or resource busy
try:
mount_point = PosixPath("/mnt")
if mount_point.exists() and mount_point.is_mount():
# This might fail if trying to remove a mount point
print(f"Is mount point: {mount_point.is_mount()}")
except OSError as e:
print(f"Device busy: {e}")
# Solution: Unmount before removing or use different operation
# Error 4: Symbolic link loops
try:
# Create a symbolic link loop (for demonstration)
link1 = PosixPath("/tmp/link1")
link2 = PosixPath("/tmp/link2")
# Clean up any existing links first
for link in [link1, link2]:
if link.exists() or link.is_symlink():
link.unlink()
# This would create a loop: link1 -> link2 -> link1
# link1.symlink_to(link2)
# link2.symlink_to(link1)
# resolved = link1.resolve() # Would raise OSError
except OSError as e:
print(f"Symbolic link loop: {e}")
# Solution: Check for loops before creating links
Debugging Tips
import os
from pathlib import PosixPath
import stat
if os.name == 'posix':
def debug_posix_path(path: PosixPath):
"""Debug POSIX path with filesystem information."""
print(f"Path: {path}")
print(f"Absolute path: {path.resolve()}")
print(f"Exists: {path.exists()}")
if path.exists():
stat_info = path.stat()
# File type information
print(f"Is file: {path.is_file()}")
print(f"Is directory: {path.is_dir()}")
print(f"Is symlink: {path.is_symlink()}")
print(f"Is socket: {path.is_socket()}")
print(f"Is fifo: {path.is_fifo()}")
print(f"Is block device: {path.is_block_device()}")
print(f"Is char device: {path.is_char_device()}")
print(f"Is mount point: {path.is_mount()}")
# Permission information
mode = stat_info.st_mode
print(f"Permissions: {oct(mode)[-3:]} ({stat.filemode(mode)})")
try:
print(f"Owner: {path.owner()}")
print(f"Group: {path.group()}")
except KeyError as e:
print(f"Cannot get owner/group: {e}")
# Size and timestamps
print(f"Size: {stat_info.st_size} bytes")
print(f"Modified: {path.stat().st_mtime}")
print(f"Accessed: {path.stat().st_atime}")
# Link information
if path.is_symlink():
try:
print(f"Link target: {path.readlink()}")
except OSError as e:
print(f"Cannot read link: {e}")
else:
print("Path does not exist")
print(f"Parent exists: {path.parent.exists()}")
print(f"Parent permissions: {oct(path.parent.stat().st_mode)[-3:] if path.parent.exists() else 'N/A'}")
def check_posix_accessibility(path: PosixPath):
"""Check various access permissions for POSIX path."""
if not path.exists():
print(f"Path {path} does not exist")
return
import os
access_checks = {
"readable": os.R_OK,
"writable": os.W_OK,
"executable": os.X_OK
}
print(f"Access permissions for {path}:")
for check_name, check_flag in access_checks.items():
accessible = os.access(path, check_flag)
print(f" {check_name}: {accessible}")
# Usage
test_path = PosixPath("/tmp")
debug_posix_path(test_path)
check_posix_accessibility(test_path)
Error Handling Patterns
import os
from pathlib import PosixPath
import logging
if os.name == 'posix':
def safe_posix_file_operation(file_path: PosixPath, operation: str, *args, **kwargs):
"""Safely perform POSIX file operations with comprehensive error handling."""
try:
# Check if path exists and is accessible
if operation in ['read_text', 'read_bytes', 'stat']:
if not file_path.exists():
raise FileNotFoundError(f"File {file_path} does not exist")
# Check read permission
if not os.access(file_path, os.R_OK):
raise PermissionError(f"No read permission for {file_path}")
elif operation in ['write_text', 'write_bytes', 'chmod']:
# Check parent directory exists and is writable
if not file_path.parent.exists():
raise FileNotFoundError(f"Parent directory {file_path.parent} does not exist")
if file_path.exists() and not os.access(file_path, os.W_OK):
raise PermissionError(f"No write permission for {file_path}")
if not file_path.exists() and not os.access(file_path.parent, os.W_OK):
raise PermissionError(f"No write permission for directory {file_path.parent}")
# Perform the operation
method = getattr(file_path, operation)
return method(*args, **kwargs)
except PermissionError as e:
logging.error(f"Permission error in {operation}: {e}")
return None
except FileNotFoundError as e:
logging.error(f"File not found in {operation}: {e}")
return None
except OSError as e:
logging.error(f"OS error in {operation}: {e}")
return None
except Exception as e:
logging.error(f"Unexpected error in {operation}: {e}")
return None
def secure_posix_directory_setup(base_path: PosixPath, structure: dict,
default_file_mode: int = 0o644,
default_dir_mode: int = 0o755):
"""Securely set up directory structure with proper POSIX permissions."""
try:
# Create base directory
base_path.mkdir(parents=True, exist_ok=True, mode=default_dir_mode)
# Create subdirectories and files
for name, config in structure.items():
item_path = base_path / name
if config.get('type') == 'directory':
mode = config.get('mode', default_dir_mode)
item_path.mkdir(exist_ok=True, mode=mode)
elif config.get('type') == 'file':
# Create file
content = config.get('content', '')
item_path.write_text(content)
# Set permissions
mode = config.get('mode', default_file_mode)
item_path.chmod(mode)
# Set ownership if specified
if 'owner' in config or 'group' in config:
# Note: Changing ownership typically requires root privileges
print(f"Would set ownership for {item_path}: {config.get('owner', 'current')}:{config.get('group', 'current')}")
return True
except Exception as e:
logging.error(f"Error setting up directory structure: {e}")
return False
# Usage example
directory_structure = {
"config": {
"type": "directory",
"mode": 0o755
},
"data": {
"type": "directory",
"mode": 0o700 # Private data directory
},
"logs": {
"type": "directory",
"mode": 0o755
},
"config/app.yaml": {
"type": "file",
"content": "app_name: myapp\nversion: 1.0",
"mode": 0o644
},
"config/secrets.yaml": {
"type": "file",
"content": "api_key: secret123",
"mode": 0o600 # Secret file
}
}
app_dir = PosixPath("/tmp/myapp")
success = secure_posix_directory_setup(app_dir, directory_structure)
print(f"Directory setup successful: {success}")
🎯 Primary Use Cases
1. Unix System Administration and Configuration
Use Case: Automate Unix system administration tasks with proper file permissions and ownership Why PosixPath: Native POSIX filesystem operations, permission management, system integration
import os
from pathlib import PosixPath
import pwd
import grp
import subprocess
from typing import Dict, List, Optional
from dataclasses import dataclass
if os.name == 'posix':
@dataclass
class SystemUser:
username: str
uid: int
gid: int
home_dir: str
shell: str
class UnixSystemManager:
"""Manage Unix system configuration and administration tasks."""
def __init__(self):
# Standard Unix system directories
self.system_dirs = {
"etc": PosixPath("/etc"),
"var": PosixPath("/var"),
"usr": PosixPath("/usr"),
"opt": PosixPath("/opt"),
"tmp": PosixPath("/tmp"),
"home": PosixPath("/home")
}
# Service directories
self.service_dirs = {
"systemd": PosixPath("/etc/systemd/system"),
"init_d": PosixPath("/etc/init.d"),
"cron_d": PosixPath("/etc/cron.d"),
"logrotate_d": PosixPath("/etc/logrotate.d")
}
def setup_application_environment(self, app_name: str,
username: Optional[str] = None) -> Dict[str, PosixPath]:
"""Set up complete application environment in Unix system."""
# Create application directories
app_dirs = {
"install": PosixPath(f"/opt/{app_name}"),
"config": PosixPath(f"/etc/{app_name}"),
"data": PosixPath(f"/var/lib/{app_name}"),
"logs": PosixPath(f"/var/log/{app_name}"),
"run": PosixPath(f"/var/run/{app_name}"),
"cache": PosixPath(f"/var/cache/{app_name}")
}
# Create directories with appropriate permissions
for dir_type, path in app_dirs.items():
if not path.exists():
print(f"Creating {dir_type} directory: {path}")
# In real implementation, would create directories
# path.mkdir(parents=True, mode=0o755)
# Set ownership if user specified
if username and dir_type in ["data", "logs", "run", "cache"]:
print(f"Would set ownership: {username}:{username}")
# chown_command = f"chown {username}:{username} {path}"
return app_dirs
def create_systemd_service(self, service_name: str, service_config: Dict) -> PosixPath:
"""Create systemd service file."""
service_file = self.service_dirs["systemd"] / f"{service_name}.service"
# Generate systemd service content
service_content = f"""[Unit]
Description={service_config.get('description', service_name)}
After=network.target
Wants=network.target
[Service]
Type={service_config.get('type', 'simple')}
User={service_config.get('user', service_name)}
Group={service_config.get('group', service_name)}
WorkingDirectory={service_config.get('working_dir', f'/opt/{service_name}')}
ExecStart={service_config.get('exec_start')}
ExecReload=/bin/kill -HUP $MAINPID
Restart={service_config.get('restart', 'on-failure')}
RestartSec={service_config.get('restart_sec', 5)}
# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths={service_config.get('working_dir', f'/opt/{service_name}')} /var/log/{service_name}
[Install]
WantedBy=multi-user.target
"""
print(f"Would create systemd service: {service_file}")
print("Service content:")
print(service_content)
# In real implementation:
# service_file.write_text(service_content)
# service_file.chmod(0o644)
return service_file
def setup_log_rotation(self, app_name: str, log_config: Dict) -> PosixPath:
"""Set up log rotation configuration."""
logrotate_file = self.service_dirs["logrotate_d"] / app_name
log_files = log_config.get('files', [f'/var/log/{app_name}/*.log'])
frequency = log_config.get('frequency', 'daily')
keep = log_config.get('keep', 30)
logrotate_content = f"""{' '.join(log_files)} {{
{frequency}
rotate {keep}
compress
delaycompress
missingok
notifempty
create 644 {app_name} {app_name}
postrotate
systemctl reload {app_name} > /dev/null 2>&1 || true
endscript
}}
"""
print(f"Would create logrotate config: {logrotate_file}")
print("Logrotate content:")
print(logrotate_content)
return logrotate_file
def create_backup_script(self, app_name: str, backup_config: Dict) -> PosixPath:
"""Create backup script for application."""
script_dir = PosixPath(f"/opt/{app_name}/scripts")
backup_script = script_dir / "backup.sh"
sources = backup_config.get('sources', [f'/var/lib/{app_name}', f'/etc/{app_name}'])
destination = backup_config.get('destination', f'/var/backups/{app_name}')
retention = backup_config.get('retention_days', 7)
backup_content = f"""#!/bin/bash
# Backup script for {app_name}
# Generated automatically
set -euo pipefail
# Configuration
BACKUP_DEST="{destination}"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="$BACKUP_DEST/{app_name}_$TIMESTAMP"
LOG_FILE="/var/log/{app_name}_backup.log"
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Logging function
log_message() {{
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}}
log_message "Starting backup for {app_name}"
# Backup sources
"""
for source in sources:
source_path = PosixPath(source)
backup_content += f"""
# Backup {source}
log_message "Backing up {source}"
if [ -d "{source}" ]; then
tar -czf "$BACKUP_DIR/{source_path.name}.tar.gz" -C "{source_path.parent}" "{source_path.name}"
elif [ -f "{source}" ]; then
cp "{source}" "$BACKUP_DIR/"
fi
"""
backup_content += f"""
# Create backup manifest
cat > "$BACKUP_DIR/manifest.txt" << EOF
Backup created: $(date)
Application: {app_name}
Sources: {', '.join(sources)}
EOF
# Compress backup
cd "$BACKUP_DEST"
tar -czf "{app_name}_$TIMESTAMP.tar.gz" "{app_name}_$TIMESTAMP"
rm -rf "$BACKUP_DIR"
log_message "Backup completed: {app_name}_$TIMESTAMP.tar.gz"
# Cleanup old backups
find "$BACKUP_DEST" -name "{app_name}_*.tar.gz" -mtime +{retention} -delete
log_message "Backup cleanup completed"
"""
print(f"Would create backup script: {backup_script}")
print("Backup script content:")
print(backup_content[:500] + "...")
# In real implementation:
# script_dir.mkdir(parents=True, exist_ok=True)
# backup_script.write_text(backup_content)
# backup_script.chmod(0o755)
return backup_script
def setup_cron_jobs(self, app_name: str, cron_jobs: List[Dict]) -> PosixPath:
"""Set up cron jobs for application."""
cron_file = self.service_dirs["cron_d"] / app_name
cron_content = f"# Cron jobs for {app_name}\n"
cron_content += f"# Generated automatically\n\n"
for job in cron_jobs:
schedule = job.get('schedule')
user = job.get('user', app_name)
command = job.get('command')
description = job.get('description', '')
if description:
cron_content += f"# {description}\n"
cron_content += f"{schedule} {user} {command}\n\n"
print(f"Would create cron file: {cron_file}")
print("Cron content:")
print(cron_content)
return cron_file
def validate_system_requirements(self, requirements: Dict) -> Dict[str, bool]:
"""Validate system requirements for application."""
validation_results = {}
# Check required directories
for req_type, paths in requirements.get('directories', {}).items():
for path_str in paths:
path = PosixPath(path_str)
validation_results[f"dir_{path}"] = path.exists() and path.is_dir()
# Check required files
for req_type, paths in requirements.get('files', {}).items():
for path_str in paths:
path = PosixPath(path_str)
validation_results[f"file_{path}"] = path.exists() and path.is_file()
# Check required commands
for command in requirements.get('commands', []):
try:
result = subprocess.run(['which', command],
capture_output=True, text=True)
validation_results[f"cmd_{command}"] = result.returncode == 0
except Exception:
validation_results[f"cmd_{command}"] = False
# Check required users
for username in requirements.get('users', []):
try:
pwd.getpwnam(username)
validation_results[f"user_{username}"] = True
except KeyError:
validation_results[f"user_{username}"] = False
# Check required groups
for groupname in requirements.get('groups', []):
try:
grp.getgrnam(groupname)
validation_results[f"group_{groupname}"] = True
except KeyError:
validation_results[f"group_{groupname}"] = False
return validation_results
# Usage
sys_mgr = UnixSystemManager()
# Set up application environment
app_dirs = sys_mgr.setup_application_environment("webapp", "webapp")
print("Application directories:")
for dir_type, path in app_dirs.items():
print(f" {dir_type}: {path}")
# Create systemd service
service_config = {
"description": "Web Application Service",
"user": "webapp",
"group": "webapp",
"working_dir": "/opt/webapp",
"exec_start": "/opt/webapp/bin/webapp",
"restart": "always"
}
service_file = sys_mgr.create_systemd_service("webapp", service_config)
# Set up log rotation
log_config = {
"files": ["/var/log/webapp/*.log"],
"frequency": "daily",
"keep": 30
}
logrotate_file = sys_mgr.setup_log_rotation("webapp", log_config)
# Create backup script
backup_config = {
"sources": ["/var/lib/webapp", "/etc/webapp"],
"destination": "/var/backups/webapp",
"retention_days": 14
}
backup_script = sys_mgr.create_backup_script("webapp", backup_config)
# Set up cron jobs
cron_jobs = [
{
"schedule": "0 2 * * *",
"user": "webapp",
"command": "/opt/webapp/scripts/backup.sh",
"description": "Daily backup at 2 AM"
},
{
"schedule": "*/15 * * * *",
"user": "webapp",
"command": "/opt/webapp/scripts/health_check.sh",
"description": "Health check every 15 minutes"
}
]
cron_file = sys_mgr.setup_cron_jobs("webapp", cron_jobs)
🎯 When to Use pathlib.PosixPath
✅ Ideal Use Cases
- Unix/Linux system administration and automation scripts
- POSIX-specific file operations requiring permission management
- Unix service configuration and system integration
- Shell script generation for POSIX systems
- Container applications running on Linux
- DevOps automation for Unix environments
- System monitoring and log management on POSIX systems
- Unix security operations requiring file permission control
❌ When NOT to Use pathlib.PosixPath
- Cross-platform applications (use
Pathfor auto-detection) - Windows-specific operations (use
WindowsPathinstead) - Pure path manipulation without I/O (use
PurePosixPathinstead) - Available on non-POSIX systems (class not available on Windows)
Alternative Solutions
- pathlib.Path: For cross-platform filesystem operations
- pathlib.PurePosixPath: For POSIX path manipulation without I/O
- os.path.posix: Legacy POSIX path operations
- subprocess: For shell command execution
- shutil: For high-level file operations
Additional Learning Resources
Official Python Resources
POSIX and Unix Documentation
Related Topics
- Unix system administration
- Linux file permissions and security
- systemd service management
- Unix shell scripting
- Container deployment and management