Skip to main content Brad's PyNotes

Sys Module: System-Specific Parameters and Functions

TL;DR

The sys module provides access to interpreter variables like sys.argv (command-line arguments), sys.path (module search paths), sys.version, sys.exit(), and functions for interacting with the Python runtime environment.

Interesting!

The sys module gives you access to the same command-line arguments that started your Python script through sys.argv, where argv[0] is always the script name and argv[1:] contains the actual arguments - just like the traditional argc/argv pattern from C programming.

Command-Line Arguments

python code snippet start

import sys

# sys.argv contains command-line arguments
# For script: python myscript.py arg1 arg2 --flag
print(f"Script name: {sys.argv[0]}")
print(f"All arguments: {sys.argv}")
print(f"Argument count: {len(sys.argv)}")

# Process arguments
if len(sys.argv) > 1:
    for i, arg in enumerate(sys.argv[1:], 1):
        print(f"Argument {i}: {arg}")
else:
    print("No arguments provided")

# Simple argument parsing
def parse_simple_args():
    """Simple command-line argument parsing"""
    args = sys.argv[1:]  # Skip script name
    
    flags = []
    params = []
    
    for arg in args:
        if arg.startswith('--'):
            flags.append(arg[2:])  # Remove --
        elif arg.startswith('-'):
            flags.append(arg[1:])   # Remove -
        else:
            params.append(arg)
    
    return flags, params

# Example usage
# python script.py file1.txt file2.txt --verbose -d
flags, params = parse_simple_args()
print(f"Flags: {flags}")      # ['verbose', 'd']
print(f"Parameters: {params}") # ['file1.txt', 'file2.txt']

python code snippet end

Python Version and Implementation

python code snippet start

import sys

# Python version information
print(f"Python version: {sys.version}")
print(f"Version info: {sys.version_info}")
print(f"Major version: {sys.version_info.major}")
print(f"Minor version: {sys.version_info.minor}")
print(f"Micro version: {sys.version_info.micro}")

# Check Python version compatibility
if sys.version_info >= (3, 8):
    print("Python 3.8+ features available")
    # Use walrus operator
    data = [1, 2, 3, 4, 5]
    if (n := len(data)) > 3:
        print(f"List has {n} items")
else:
    print("Upgrade to Python 3.8+ for latest features")

# Platform and implementation details
print(f"Platform: {sys.platform}")
print(f"Implementation: {sys.implementation.name}")
print(f"Implementation version: {sys.implementation.version}")

# Check for specific platforms
if sys.platform.startswith('win'):
    print("Running on Windows")
elif sys.platform.startswith('darwin'):
    print("Running on macOS")
elif sys.platform.startswith('linux'):
    print("Running on Linux")

# Byte order (endianness)
print(f"Byte order: {sys.byteorder}")

# Maximum integer size
print(f"Max size: {sys.maxsize}")

python code snippet end

Module Search Path

python code snippet start

import sys

# Display module search paths
print("Python module search paths:")
for i, path in enumerate(sys.path):
    print(f"  {i}: {path}")

# Add custom module path
custom_path = "/path/to/my/modules"
if custom_path not in sys.path:
    sys.path.insert(0, custom_path)  # Add at beginning for highest priority
    print(f"Added {custom_path} to sys.path")

# Remove a path
try:
    sys.path.remove(custom_path)
    print(f"Removed {custom_path} from sys.path")
except ValueError:
    print(f"{custom_path} not in sys.path")

# Check if module can be imported
def can_import(module_name):
    """Check if a module can be imported"""
    try:
        __import__(module_name)
        return True
    except ImportError:
        return False

print(f"Can import 'requests': {can_import('requests')}")
print(f"Can import 'json': {can_import('json')}")

# Find module location
import json
print(f"json module location: {json.__file__}")

python code snippet end

Standard Input, Output, and Error

python code snippet start

import sys

# Standard streams
print("This goes to stdout", file=sys.stdout)
print("This goes to stderr", file=sys.stderr)

# Read from stdin
print("Enter your name: ", end='')
sys.stdout.flush()  # Force output before input
name = sys.stdin.readline().strip()
print(f"Hello, {name}!")

# Redirect output
import io

# Capture stdout
old_stdout = sys.stdout
sys.stdout = captured_output = io.StringIO()

print("This is captured")
print("This too")

# Restore stdout and get captured content
sys.stdout = old_stdout
captured_text = captured_output.getvalue()
print(f"Captured: {repr(captured_text)}")

# Context manager for output redirection
class CaptureOutput:
    def __init__(self):
        self.captured = io.StringIO()
        
    def __enter__(self):
        self.old_stdout = sys.stdout
        sys.stdout = self.captured
        return self
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        sys.stdout = self.old_stdout
        
    def get_output(self):
        return self.captured.getvalue()

# Usage
with CaptureOutput() as capture:
    print("This is captured")
    print("So is this")

print("Captured output:", repr(capture.get_output()))

python code snippet end

Exiting and Exception Handling

python code snippet start

import sys

def graceful_exit(message="", code=0):
    """Exit with optional message and code"""
    if message:
        print(message, file=sys.stderr)
    sys.exit(code)

# Exit codes
def process_file(filename):
    """Process a file with proper exit codes"""
    try:
        with open(filename, 'r') as f:
            content = f.read()
        print(f"Processed {len(content)} characters")
        return True
    except FileNotFoundError:
        print(f"Error: File '{filename}' not found", file=sys.stderr)
        sys.exit(1)  # File not found
    except PermissionError:
        print(f"Error: Permission denied for '{filename}'", file=sys.stderr)
        sys.exit(2)  # Permission error
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(3)  # General error

# Exception information
def show_exception_info():
    """Display current exception information"""
    exc_type, exc_value, exc_traceback = sys.exc_info()
    
    if exc_type is not None:
        print(f"Exception type: {exc_type.__name__}")
        print(f"Exception value: {exc_value}")
        print(f"Traceback object: {exc_traceback}")
    else:
        print("No current exception")

# Example with exception handling
try:
    x = 1 / 0
except ZeroDivisionError:
    print("Caught division by zero:")
    show_exception_info()

# Exit handler
import atexit

def cleanup():
    """Function called on exit"""
    print("Cleaning up before exit...")

atexit.register(cleanup)

# Uncomment to test exit
# graceful_exit("Goodbye!", 0)

python code snippet end

Memory and Performance Information

python code snippet start

import sys

# Memory usage
def get_object_size(obj):
    """Get size of object in bytes"""
    return sys.getsizeof(obj)

# Compare memory usage of different data structures
data = list(range(1000))
print(f"List of 1000 integers: {get_object_size(data)} bytes")

data_tuple = tuple(range(1000))
print(f"Tuple of 1000 integers: {get_object_size(data_tuple)} bytes")

data_set = set(range(1000))
print(f"Set of 1000 integers: {get_object_size(data_set)} bytes")

data_dict = {i: i for i in range(1000)}
print(f"Dict of 1000 key-value pairs: {get_object_size(data_dict)} bytes")

# Deep memory analysis
def analyze_memory_usage(obj, name="object"):
    """Analyze memory usage of an object"""
    size = sys.getsizeof(obj)
    print(f"{name}: {size} bytes")
    
    # For containers, analyze contents
    if hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes)):
        try:
            items = list(obj)
            if items:
                item_sizes = [sys.getsizeof(item) for item in items[:10]]  # First 10 items
                avg_item_size = sum(item_sizes) / len(item_sizes)
                print(f"  Average item size: {avg_item_size:.1f} bytes")
                print(f"  Estimated total content: {avg_item_size * len(items):.0f} bytes")
        except:
            pass

# Example analysis
analyze_memory_usage([1, 2, 3, 4, 5], "Small list")
analyze_memory_usage(list(range(10000)), "Large list")
analyze_memory_usage("Hello, World!", "String")

# Reference count (CPython specific)
import sys

x = [1, 2, 3]
print(f"Reference count for x: {sys.getrefcount(x)}")

y = x  # Create another reference
print(f"Reference count after y = x: {sys.getrefcount(x)}")

del y  # Remove reference
print(f"Reference count after del y: {sys.getrefcount(x)}")

python code snippet end

Recursion and Call Stack

python code snippet start

import sys

# Recursion limit
print(f"Current recursion limit: {sys.getrecursionlimit()}")

# Set recursion limit (be careful!)
original_limit = sys.getrecursionlimit()
sys.setrecursionlimit(2000)
print(f"New recursion limit: {sys.getrecursionlimit()}")

# Restore original limit
sys.setrecursionlimit(original_limit)

# Test recursion depth
def recursive_function(depth=0):
    """Test function to demonstrate recursion depth"""
    if depth > 10:  # Prevent infinite recursion in demo
        return depth
    return recursive_function(depth + 1)

try:
    max_depth = recursive_function()
    print(f"Reached depth: {max_depth}")
except RecursionError:
    print("Hit recursion limit")

# Stack frame inspection
import inspect

def stack_info():
    """Display current call stack information"""
    frame = sys._getframe()
    
    print("Current stack frames:")
    depth = 0
    while frame:
        filename = frame.f_code.co_filename
        line_number = frame.f_lineno
        function_name = frame.f_code.co_name
        
        print(f"  {depth}: {function_name} in {filename}:{line_number}")
        
        frame = frame.f_back
        depth += 1
        
        if depth > 10:  # Limit output
            break

def level1():
    level2()

def level2():
    level3()

def level3():
    stack_info()

# Uncomment to see stack trace
# level1()

python code snippet end

Practical Command-Line Tools

File Processor Script

python code snippet start

#!/usr/bin/env python3
import sys
import os

def main():
    """Main function for file processing script"""
    
    # Check arguments
    if len(sys.argv) < 2:
        print("Usage: python script.py <filename> [options]", file=sys.stderr)
        print("Options:")
        print("  --count    Count lines")
        print("  --upper    Convert to uppercase")
        print("  --verbose  Verbose output")
        sys.exit(1)
    
    filename = sys.argv[1]
    options = sys.argv[2:]
    
    # Parse options
    count_lines = '--count' in options
    to_upper = '--upper' in options
    verbose = '--verbose' in options
    
    if verbose:
        print(f"Processing file: {filename}")
        print(f"Options: {options}")
    
    # Check if file exists
    if not os.path.exists(filename):
        print(f"Error: File '{filename}' not found", file=sys.stderr)
        sys.exit(1)
    
    try:
        with open(filename, 'r') as f:
            lines = f.readlines()
        
        if count_lines:
            print(f"Line count: {len(lines)}")
        
        if to_upper:
            for i, line in enumerate(lines):
                print(f"{i+1}: {line.upper().rstrip()}")
        elif not count_lines:  # Default: just display
            for i, line in enumerate(lines):
                print(f"{i+1}: {line.rstrip()}")
                
    except PermissionError:
        print(f"Error: Permission denied for '{filename}'", file=sys.stderr)
        sys.exit(2)
    except Exception as e:
        print(f"Error processing file: {e}", file=sys.stderr)
        sys.exit(3)

if __name__ == "__main__":
    main()

python code snippet end

System Information Tool

python code snippet start

import sys
import platform
import os

def system_info():
    """Display comprehensive system information"""
    
    print("=== Python System Information ===")
    print(f"Python Version: {sys.version}")
    print(f"Python Executable: {sys.executable}")
    print(f"Platform: {sys.platform}")
    print(f"Architecture: {platform.architecture()}")
    print(f"Machine: {platform.machine()}")
    print(f"Processor: {platform.processor()}")
    print(f"System: {platform.system()} {platform.release()}")
    
    print(f"\n=== Python Runtime ===")
    print(f"Implementation: {sys.implementation.name}")
    print(f"Implementation Version: {sys.implementation.version}")
    print(f"Byte Order: {sys.byteorder}")
    print(f"Max Integer Size: {sys.maxsize}")
    print(f"Recursion Limit: {sys.getrecursionlimit()}")
    
    print(f"\n=== Environment ===")
    print(f"Current Working Directory: {os.getcwd()}")
    print(f"Home Directory: {os.path.expanduser('~')}")
    
    print(f"\n=== Module Search Paths ===")
    for i, path in enumerate(sys.path[:5]):  # Show first 5
        print(f"  {i}: {path}")
    if len(sys.path) > 5:
        print(f"  ... and {len(sys.path) - 5} more paths")
    
    print(f"\n=== Command Line ===")
    if len(sys.argv) > 0:
        print(f"Script: {sys.argv[0]}")
        if len(sys.argv) > 1:
            print(f"Arguments: {sys.argv[1:]}")
    
    # Memory usage of common objects
    print(f"\n=== Memory Usage Examples ===")
    objects = [
        ("Empty list", []),
        ("List of 100 ints", list(range(100))),
        ("Empty dict", {}),
        ("Dict with 10 items", {i: i for i in range(10)}),
        ("String 'Hello'", "Hello"),
        ("String 100 chars", "x" * 100)
    ]
    
    for name, obj in objects:
        size = sys.getsizeof(obj)
        print(f"  {name}: {size} bytes")

if __name__ == "__main__":
    # Check for help flag
    if "--help" in sys.argv or "-h" in sys.argv:
        print("System Information Tool")
        print("Usage: python sysinfo.py [--help]")
        print("Displays comprehensive Python system information")
        sys.exit(0)
    
    system_info()

python code snippet end

Environment Configuration Tool

python code snippet start

import sys
import os
import json

def manage_python_path():
    """Tool for managing Python module search paths"""
    
    if len(sys.argv) < 2:
        print("Python Path Manager")
        print("Usage: python pathman.py <command> [arguments]")
        print("Commands:")
        print("  list                 - Show current paths")
        print("  add <path>          - Add path to sys.path")
        print("  remove <path>       - Remove path from sys.path")
        print("  save <file>         - Save current paths to file")
        print("  load <file>         - Load paths from file")
        sys.exit(1)
    
    command = sys.argv[1]
    
    if command == "list":
        print("Current Python module search paths:")
        for i, path in enumerate(sys.path):
            exists = "✓" if os.path.exists(path) else "✗"
            print(f"  {i:2d}: {exists} {path}")
    
    elif command == "add":
        if len(sys.argv) < 3:
            print("Error: Please specify path to add")
            sys.exit(1)
        
        new_path = sys.argv[2]
        if not os.path.exists(new_path):
            print(f"Warning: Path '{new_path}' does not exist")
        
        if new_path not in sys.path:
            sys.path.insert(0, new_path)
            print(f"Added '{new_path}' to sys.path")
        else:
            print(f"Path '{new_path}' already in sys.path")
    
    elif command == "remove":
        if len(sys.argv) < 3:
            print("Error: Please specify path to remove")
            sys.exit(1)
        
        path_to_remove = sys.argv[2]
        try:
            sys.path.remove(path_to_remove)
            print(f"Removed '{path_to_remove}' from sys.path")
        except ValueError:
            print(f"Path '{path_to_remove}' not found in sys.path")
    
    elif command == "save":
        if len(sys.argv) < 3:
            print("Error: Please specify filename")
            sys.exit(1)
        
        filename = sys.argv[2]
        path_data = {
            'python_version': sys.version,
            'platform': sys.platform,
            'paths': sys.path
        }
        
        try:
            with open(filename, 'w') as f:
                json.dump(path_data, f, indent=2)
            print(f"Saved {len(sys.path)} paths to '{filename}'")
        except Exception as e:
            print(f"Error saving to '{filename}': {e}")
            sys.exit(1)
    
    elif command == "load":
        if len(sys.argv) < 3:
            print("Error: Please specify filename")
            sys.exit(1)
        
        filename = sys.argv[2]
        try:
            with open(filename, 'r') as f:
                path_data = json.load(f)
            
            print(f"Loaded paths from '{filename}'")
            print(f"  Saved Python version: {path_data.get('python_version', 'unknown')}")
            print(f"  Saved platform: {path_data.get('platform', 'unknown')}")
            
            for path in path_data.get('paths', []):
                if path not in sys.path:
                    sys.path.append(path)
                    print(f"  Added: {path}")
                else:
                    print(f"  Already present: {path}")
        
        except FileNotFoundError:
            print(f"Error: File '{filename}' not found")
            sys.exit(1)
        except json.JSONDecodeError:
            print(f"Error: Invalid JSON in '{filename}'")
            sys.exit(1)
        except Exception as e:
            print(f"Error loading from '{filename}': {e}")
            sys.exit(1)
    
    else:
        print(f"Error: Unknown command '{command}'")
        sys.exit(1)

if __name__ == "__main__":
    manage_python_path()

python code snippet end

The sys module is essential for creating robust Python applications that need to interact with the runtime environment, handle command-line arguments, and manage system-specific functionality.

The sys module complements os module for system operations and supports module management through sys.path manipulation.

Reference: Python Sys Module Documentation