python
exercises
exercises.py🐍python
"""
12 - Real Development Modules: Exercises
Practice os, sys, logging, argparse, pathlib.
"""
print("=" * 60)
print("REAL DEVELOPMENT MODULES EXERCISES")
print("=" * 60)
import os
import sys
from pathlib import Path
import logging
import argparse
import tempfile
# =============================================================================
# EXERCISE 1: Directory Explorer
# Create a function that takes a path and prints all files
# with their sizes in a formatted way.
# =============================================================================
print("\n--- Exercise 1: Directory Explorer ---")
# Your code here:
# Test:
# explore_directory('/path/to/folder')
# =============================================================================
# EXERCISE 2: Find Large Files
# Create a function that finds all files larger than a given size
# in a directory (recursively).
# =============================================================================
print("\n--- Exercise 2: Find Large Files ---")
# Your code here:
# Test:
# large_files = find_large_files('/path', min_size_bytes=1000000)
# =============================================================================
# EXERCISE 3: Environment Configuration
# Create a function that reads configuration from environment variables
# with defaults and type conversion.
# =============================================================================
print("\n--- Exercise 3: Environment Config ---")
# Your code here:
# Test:
# config = get_config()
# print(config)
# =============================================================================
# EXERCISE 4: Custom Logger
# Create a setup_logger function that creates a logger with both
# console and file handlers with different formats.
# =============================================================================
print("\n--- Exercise 4: Custom Logger ---")
# Your code here:
# Test:
# logger = setup_logger('myapp', 'app.log')
# logger.info("Test message")
# =============================================================================
# EXERCISE 5: File Organizer
# Create a function that organizes files in a directory by extension
# into subdirectories (e.g., .py -> python/, .txt -> text/).
# =============================================================================
print("\n--- Exercise 5: File Organizer ---")
# Your code here:
# Test:
# organize_by_extension('/path/to/messy/folder')
# =============================================================================
# EXERCISE 6: Path Statistics
# Create a function that returns statistics about paths in a directory:
# - Total files
# - Total directories
# - Total size
# - File types (by extension)
# =============================================================================
print("\n--- Exercise 6: Path Statistics ---")
# Your code here:
# Test:
# stats = get_path_stats('/path/to/folder')
# =============================================================================
# EXERCISE 7: Argparse CLI Tool
# Create a CLI tool with subcommands: create, delete, list
# for managing a simple todo list stored in a JSON file.
# =============================================================================
print("\n--- Exercise 7: CLI Todo Tool ---")
# Your code here:
# Usage:
# python script.py create "Buy groceries"
# python script.py list
# python script.py delete 1
# =============================================================================
# EXERCISE 8: Log Parser
# Create a function that parses log files and extracts:
# - Error counts by hour
# - Most common error messages
# - First and last log timestamps
# =============================================================================
print("\n--- Exercise 8: Log Parser ---")
# Your code here:
# Test:
# result = parse_logs('application.log')
# =============================================================================
# SOLUTIONS
# =============================================================================
print("\n\n" + "=" * 60)
print("SOLUTIONS")
print("=" * 60)
# SOLUTION 1
print("\n--- Solution 1: Directory Explorer ---")
def explore_directory(path):
"""Print all files in directory with their sizes."""
path = Path(path)
if not path.exists():
print(f"Path not found: {path}")
return
total_size = 0
for item in sorted(path.iterdir()):
if item.is_file():
size = item.stat().st_size
total_size += size
print(f" {item.name:<30} {size:>10,} bytes")
else:
print(f" {item.name:<30} [DIR]")
print(f"\nTotal size: {total_size:,} bytes")
# Demo with temp directory
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
(tmp / 'file1.txt').write_text('Hello' * 100)
(tmp / 'file2.py').write_text('print("world")')
(tmp / 'subdir').mkdir()
explore_directory(tmpdir)
# SOLUTION 2
print("\n--- Solution 2: Find Large Files ---")
def find_large_files(path, min_size_bytes=1000):
"""Find files larger than min_size_bytes."""
path = Path(path)
large_files = []
for file in path.rglob('*'):
if file.is_file():
size = file.stat().st_size
if size >= min_size_bytes:
large_files.append((file, size))
return sorted(large_files, key=lambda x: x[1], reverse=True)
# Demo
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
(tmp / 'small.txt').write_text('small')
(tmp / 'large.txt').write_text('x' * 2000)
(tmp / 'subdir').mkdir()
(tmp / 'subdir' / 'huge.txt').write_text('y' * 5000)
large = find_large_files(tmpdir, min_size_bytes=1000)
print("Large files:")
for file, size in large:
print(f" {file.name}: {size} bytes")
# SOLUTION 3
print("\n--- Solution 3: Environment Config ---")
def get_config():
"""Get configuration from environment variables."""
config = {
'debug': os.environ.get('DEBUG', 'false').lower() == 'true',
'port': int(os.environ.get('PORT', '8080')),
'host': os.environ.get('HOST', 'localhost'),
'database_url': os.environ.get('DATABASE_URL', 'sqlite:///db.sqlite'),
'log_level': os.environ.get('LOG_LEVEL', 'INFO'),
}
return config
# Demo
os.environ['DEBUG'] = 'true'
os.environ['PORT'] = '3000'
config = get_config()
print(f"Config: {config}")
# SOLUTION 4
print("\n--- Solution 4: Custom Logger ---")
def setup_logger(name, log_file=None, level=logging.DEBUG):
"""Create a logger with console and optional file handler."""
logger = logging.getLogger(name)
logger.setLevel(level)
logger.handlers = [] # Clear existing handlers
# Console handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_format = logging.Formatter('%(levelname)s - %(message)s')
console_handler.setFormatter(console_format)
logger.addHandler(console_handler)
# File handler
if log_file:
file_handler = logging.FileHandler(log_file)
file_handler.setLevel(logging.DEBUG)
file_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(file_format)
logger.addHandler(file_handler)
return logger
# Demo
with tempfile.NamedTemporaryFile(suffix='.log', delete=False) as f:
log_file = f.name
logger = setup_logger('myapp', log_file)
logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
print(f"\nLog file contents:")
print(Path(log_file).read_text())
os.remove(log_file)
# SOLUTION 5
print("\n--- Solution 5: File Organizer ---")
def organize_by_extension(path, dry_run=True):
"""Organize files into subdirectories by extension."""
path = Path(path)
extension_map = {
'.py': 'python',
'.txt': 'text',
'.jpg': 'images',
'.png': 'images',
'.pdf': 'documents',
}
moves = []
for file in path.iterdir():
if file.is_file():
ext = file.suffix.lower()
folder_name = extension_map.get(ext, 'other')
dest_folder = path / folder_name
moves.append((file, dest_folder / file.name))
if dry_run:
print("Would move:")
for src, dst in moves:
print(f" {src.name} -> {dst.parent.name}/{dst.name}")
else:
for src, dst in moves:
dst.parent.mkdir(exist_ok=True)
src.rename(dst)
return moves
# Demo
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
(tmp / 'script.py').write_text('# python')
(tmp / 'notes.txt').write_text('notes')
(tmp / 'data.csv').write_text('a,b,c')
organize_by_extension(tmpdir)
# SOLUTION 6
print("\n--- Solution 6: Path Statistics ---")
def get_path_stats(path):
"""Get statistics about a directory."""
path = Path(path)
stats = {
'total_files': 0,
'total_dirs': 0,
'total_size': 0,
'file_types': {},
}
for item in path.rglob('*'):
if item.is_file():
stats['total_files'] += 1
stats['total_size'] += item.stat().st_size
ext = item.suffix.lower() or 'no extension'
stats['file_types'][ext] = stats['file_types'].get(ext, 0) + 1
elif item.is_dir():
stats['total_dirs'] += 1
return stats
# Demo
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
(tmp / 'file1.py').write_text('# python')
(tmp / 'file2.py').write_text('# python')
(tmp / 'data.txt').write_text('data')
(tmp / 'subdir').mkdir()
(tmp / 'subdir' / 'nested.txt').write_text('nested')
stats = get_path_stats(tmpdir)
print("Directory statistics:")
for key, value in stats.items():
print(f" {key}: {value}")
# SOLUTION 8
print("\n--- Solution 8: Log Parser ---")
from collections import Counter
import re
def parse_logs(log_content):
"""Parse log content and extract statistics."""
result = {
'error_counts': Counter(),
'common_errors': [],
'first_timestamp': None,
'last_timestamp': None,
}
# Pattern: 2024-01-01 10:00:00 - LEVEL - message
pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) - (\w+) - (.+)'
timestamps = []
error_messages = []
for line in log_content.strip().split('\n'):
match = re.match(pattern, line)
if match:
timestamp, level, message = match.groups()
timestamps.append(timestamp)
if level == 'ERROR':
hour = timestamp.split()[1].split(':')[0]
result['error_counts'][hour] += 1
error_messages.append(message)
if timestamps:
result['first_timestamp'] = timestamps[0]
result['last_timestamp'] = timestamps[-1]
result['common_errors'] = Counter(error_messages).most_common(3)
return result
# Demo
sample_logs = """
2024-01-01 10:00:00 - INFO - Application started
2024-01-01 10:15:00 - ERROR - Database connection failed
2024-01-01 10:30:00 - ERROR - Database connection failed
2024-01-01 11:00:00 - INFO - Retry successful
2024-01-01 11:30:00 - ERROR - Timeout error
2024-01-01 12:00:00 - INFO - Shutdown complete
"""
result = parse_logs(sample_logs)
print("Log analysis:")
print(f" First: {result['first_timestamp']}")
print(f" Last: {result['last_timestamp']}")
print(f" Errors by hour: {dict(result['error_counts'])}")
print(f" Common errors: {result['common_errors']}")
print("\n" + "=" * 60)
print("END OF EXERCISES")
print("=" * 60)