šŸ Week 1: Python Foundations

Day 5: Lists, Dictionaries & File I/O

Duration: 5 Hours

šŸ“š Learning Objectives

By the end of this session, you will be able to:

  • Create and manipulate lists
  • Work with dictionaries for structured data
  • Read from and write to files
  • Use JSON for data serialization
  • Complete a mini project integrating all Week 1 concepts

šŸ“– Core Concepts (2 Hours)

Lists - Ordered Collections

Lists store multiple items in a single variable. They're ordered, mutable (changeable), and allow duplicates.

# Creating lists servers = ["web-01", "web-02", "db-01"] ports = [80, 443, 8080, 3306] mixed = ["server", 8080, True, 3.14] empty = [] # Accessing elements (0-indexed) print(servers[0]) # web-01 print(servers[-1]) # db-01 (last item) # Slicing print(servers[0:2]) # ['web-01', 'web-02'] print(ports[1:]) # [443, 8080, 3306] # Modifying lists servers[0] = "web-server-01" # Change item servers.append("cache-01") # Add to end servers.insert(0, "lb-01") # Insert at position servers.extend(["app-01", "app-02"]) # Add multiple # Removing items servers.remove("db-01") # Remove by value last = servers.pop() # Remove and return last del servers[0] # Delete by index # List operations print(len(servers)) # Length print("web-01" in servers) # Check membership print(servers.index("web-02")) # Find index print(servers.count("web-01")) # Count occurrences

List Methods

# Common list methods numbers = [3, 1, 4, 1, 5, 9, 2, 6] # Sorting numbers.sort() # Sort in place print(numbers) # [1, 1, 2, 3, 4, 5, 6, 9] numbers.sort(reverse=True) # Descending print(numbers) # [9, 6, 5, 4, 3, 2, 1, 1] # Sorted (returns new list) original = [3, 1, 4] sorted_list = sorted(original) print(original) # [3, 1, 4] (unchanged) print(sorted_list) # [1, 3, 4] # Reverse servers = ["a", "b", "c"] servers.reverse() print(servers) # ['c', 'b', 'a'] # Copy original = [1, 2, 3] copy = original.copy() # New list

List Comprehensions

# List comprehension = concise way to create lists # Traditional way squares = [] for x in range(5): squares.append(x ** 2) # List comprehension squares = [x ** 2 for x in range(5)] print(squares) # [0, 1, 4, 9, 16] # With condition evens = [x for x in range(10) if x % 2 == 0] print(evens) # [0, 2, 4, 6, 8] # DevOps examples servers = ["web-01", "web-02", "db-01", "cache-01"] # Get only web servers web_servers = [s for s in servers if s.startswith("web")] print(web_servers) # ['web-01', 'web-02'] # Create server URLs urls = [f"http://{s}.example.com" for s in servers] print(urls) # Transform data logs = [" error: failed ", " info: started "] clean_logs = [log.strip().upper() for log in logs] print(clean_logs) # ['ERROR: FAILED', 'INFO: STARTED']

Dictionaries - Key-Value Pairs

# Dictionaries store key-value pairs server = { "name": "web-01", "ip": "192.168.1.10", "port": 8080, "active": True } # Accessing values print(server["name"]) # web-01 print(server.get("name")) # web-01 (safer) print(server.get("missing", "default")) # default # Modifying server["port"] = 443 # Change value server["region"] = "us-east" # Add new key del server["active"] # Delete key # Dictionary methods print(server.keys()) # All keys print(server.values()) # All values print(server.items()) # Key-value pairs # Check if key exists if "name" in server: print("Has name") # Iterate for key, value in server.items(): print(f"{key}: {value}")

Nested Structures

# List of dictionaries (common pattern!) servers = [ {"name": "web-01", "cpu": 45, "memory": 60}, {"name": "web-02", "cpu": 85, "memory": 75}, {"name": "db-01", "cpu": 30, "memory": 90}, ] # Access nested data print(servers[0]["name"]) # web-01 # Iterate for server in servers: print(f"{server['name']}: CPU={server['cpu']}%") # Dictionary of lists config = { "web_servers": ["web-01", "web-02"], "db_servers": ["db-01"], "ports": [80, 443, 8080] } print(config["web_servers"][0]) # web-01 # Dictionary of dictionaries infrastructure = { "production": { "web": {"count": 3, "type": "t3.large"}, "db": {"count": 2, "type": "r5.xlarge"} }, "staging": { "web": {"count": 1, "type": "t3.small"}, "db": {"count": 1, "type": "t3.medium"} } } print(infrastructure["production"]["web"]["count"]) # 3

File Reading

# Reading files # Method 1: read() - entire file as string with open("config.txt", "r") as file: content = file.read() print(content) # Method 2: readline() - one line at a time with open("config.txt", "r") as file: line = file.readline() while line: print(line.strip()) line = file.readline() # Method 3: readlines() - list of lines with open("config.txt", "r") as file: lines = file.readlines() for line in lines: print(line.strip()) # Method 4: iterate directly (best!) with open("config.txt", "r") as file: for line in file: print(line.strip()) # The 'with' statement automatically closes the file # Even if an error occurs!

File Writing

# Writing files # Write mode ('w') - creates/overwrites file with open("output.txt", "w") as file: file.write("Hello, World!\n") file.write("This is line 2\n") # Append mode ('a') - adds to end with open("output.txt", "a") as file: file.write("This line was appended\n") # Write multiple lines lines = ["Line 1", "Line 2", "Line 3"] with open("output.txt", "w") as file: for line in lines: file.write(line + "\n") # Or use writelines() with open("output.txt", "w") as file: file.writelines([line + "\n" for line in lines]) # DevOps: Write log file def log(message, filename="app.log"): """Append message to log file with timestamp.""" from datetime import datetime timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") with open(filename, "a") as file: file.write(f"[{timestamp}] {message}\n") log("Application started") log("Connection established")

JSON - Data Serialization

import json # Python dict to JSON string server = { "name": "web-01", "ip": "192.168.1.10", "ports": [80, 443], "active": True } json_string = json.dumps(server) print(json_string) # Pretty print JSON json_pretty = json.dumps(server, indent=2) print(json_pretty) # JSON string to Python dict json_data = '{"name": "web-02", "port": 8080}' server = json.loads(json_data) print(server["name"]) # web-02 # Write JSON to file with open("config.json", "w") as file: json.dump(server, file, indent=2) # Read JSON from file with open("config.json", "r") as file: config = json.load(file) print(config)

šŸ”¬ Hands-on Lab (2.5 Hours)

Lab 1: List Operations

  • Create and manipulate server lists
  • Use list comprehensions
  • Sort and filter data
# Lab 1: list_operations.py # Server inventory servers = [ "web-01", "web-02", "web-03", "db-01", "db-02", "cache-01", "api-01", "api-02" ] print("=== Server Inventory ===\n") print(f"Total servers: {len(servers)}") print(f"All servers: {servers}") # Filter by type web_servers = [s for s in servers if s.startswith("web")] db_servers = [s for s in servers if s.startswith("db")] api_servers = [s for s in servers if s.startswith("api")] print(f"\nWeb servers ({len(web_servers)}): {web_servers}") print(f"DB servers ({len(db_servers)}): {db_servers}") print(f"API servers ({len(api_servers)}): {api_servers}") # Create FQDNs domain = "example.com" fqdns = [f"{server}.{domain}" for server in servers] print(f"\nFQDNs:") for fqdn in fqdns: print(f" - {fqdn}") # Server with ports server_ports = { "web-01": 80, "web-02": 80, "web-03": 443, "db-01": 5432, "db-02": 5432, "cache-01": 6379, "api-01": 8080, "api-02": 8080 } # Find servers on specific ports port_80 = [s for s, p in server_ports.items() if p == 80] print(f"\nServers on port 80: {port_80}")

Lab 2: Dictionary Practice

  • Create server configuration dictionaries
  • Work with nested structures
  • Update and iterate data
# Lab 2: dict_practice.py # Server inventory with full details servers = [ { "name": "web-01", "ip": "192.168.1.10", "cpu": 45, "memory": 60, "disk": 70, "status": "running" }, { "name": "web-02", "ip": "192.168.1.11", "cpu": 85, "memory": 75, "disk": 65, "status": "running" }, { "name": "db-01", "ip": "192.168.1.20", "cpu": 30, "memory": 90, "disk": 85, "status": "running" }, { "name": "cache-01", "ip": "192.168.1.30", "cpu": 20, "memory": 40, "disk": 30, "status": "stopped" } ] print("=== Server Dashboard ===\n") # Display all servers print(f"{'Name':<12} {'IP':<16} {'CPU':>5} {'Mem':>5} {'Disk':>5} {'Status':<10}") print("-" * 60) for server in servers: print(f"{server['name']:<12} {server['ip']:<16} " f"{server['cpu']:>4}% {server['memory']:>4}% " f"{server['disk']:>4}% {server['status']:<10}") # Find servers with high resource usage print("\n=== Alerts ===") for server in servers: alerts = [] if server["cpu"] > 80: alerts.append(f"High CPU ({server['cpu']}%)") if server["memory"] > 80: alerts.append(f"High Memory ({server['memory']}%)") if server["disk"] > 80: alerts.append(f"High Disk ({server['disk']}%)") if alerts: print(f"\n{server['name']}:") for alert in alerts: print(f" āš ļø {alert}") # Calculate averages total_cpu = sum(s["cpu"] for s in servers) avg_cpu = total_cpu / len(servers) print(f"\n=== Summary ===") print(f"Average CPU: {avg_cpu:.1f}%") running = [s for s in servers if s["status"] == "running"] print(f"Running servers: {len(running)}/{len(servers)}")

Lab 3: File Operations

  • Read configuration from file
  • Write reports to files
  • Work with log files
# Lab 3: file_operations.py # First, create a sample config file config_content = """# Server Configuration host=localhost port=8080 debug=true max_connections=100 timeout=30 """ # Write config file with open("server.conf", "w") as file: file.write(config_content) print("Created server.conf") # Read and parse config file def read_config(filename): """Read config file and return as dictionary.""" config = {} with open(filename, "r") as file: for line in file: line = line.strip() # Skip empty lines and comments if not line or line.startswith("#"): continue # Parse key=value if "=" in line: key, value = line.split("=", 1) config[key.strip()] = value.strip() return config config = read_config("server.conf") print("\nParsed configuration:") for key, value in config.items(): print(f" {key}: {value}") # Generate a report file def generate_report(servers, filename): """Generate server status report.""" with open(filename, "w") as file: file.write("=" * 50 + "\n") file.write(" SERVER STATUS REPORT\n") file.write("=" * 50 + "\n\n") for server in servers: file.write(f"Server: {server['name']}\n") file.write(f" IP: {server['ip']}\n") file.write(f" Status: {server['status']}\n") file.write(f" Resources: CPU={server['cpu']}%, " f"Memory={server['memory']}%\n") file.write("\n") file.write("=" * 50 + "\n") file.write(f"Total servers: {len(servers)}\n") print(f"\nReport written to {filename}") # Test report generation servers = [ {"name": "web-01", "ip": "10.0.0.1", "status": "running", "cpu": 45, "memory": 60}, {"name": "db-01", "ip": "10.0.0.2", "status": "running", "cpu": 30, "memory": 80}, ] generate_report(servers, "report.txt") # Read and display the report print("\n--- Generated Report ---") with open("report.txt", "r") as file: print(file.read())

Lab 4: Mini Project - Server Inventory System

  • Combine all Week 1 concepts
  • Use JSON for data storage
  • Create interactive menu
# Lab 4: inventory_system.py # Mini Project: Server Inventory Management System import json from datetime import datetime # File for storing data DATA_FILE = "inventory.json" def load_inventory(): """Load inventory from JSON file.""" try: with open(DATA_FILE, "r") as file: return json.load(file) except FileNotFoundError: return [] def save_inventory(inventory): """Save inventory to JSON file.""" with open(DATA_FILE, "w") as file: json.dump(inventory, file, indent=2) def list_servers(inventory): """Display all servers.""" if not inventory: print("\nNo servers in inventory.") return print(f"\n{'Name':<15} {'IP':<16} {'Type':<10} {'Status':<10}") print("-" * 55) for server in inventory: print(f"{server['name']:<15} {server['ip']:<16} " f"{server['type']:<10} {server['status']:<10}") def add_server(inventory): """Add a new server.""" print("\n--- Add New Server ---") name = input("Server name: ") ip = input("IP address: ") server_type = input("Type (web/db/cache): ") server = { "name": name, "ip": ip, "type": server_type, "status": "running", "added": datetime.now().strftime("%Y-%m-%d %H:%M") } inventory.append(server) save_inventory(inventory) print(f"\nāœ“ Server '{name}' added successfully!") def remove_server(inventory): """Remove a server.""" name = input("\nEnter server name to remove: ") for i, server in enumerate(inventory): if server["name"] == name: inventory.pop(i) save_inventory(inventory) print(f"\nāœ“ Server '{name}' removed.") return print(f"\nāœ— Server '{name}' not found.") def search_servers(inventory): """Search servers by type.""" search_type = input("\nEnter server type to search: ") results = [s for s in inventory if s["type"] == search_type] if results: print(f"\nFound {len(results)} {search_type} server(s):") for server in results: print(f" - {server['name']} ({server['ip']})") else: print(f"\nNo {search_type} servers found.") def generate_summary(inventory): """Generate inventory summary.""" if not inventory: print("\nNo servers to summarize.") return print("\n" + "=" * 40) print(" INVENTORY SUMMARY") print("=" * 40) # Count by type types = {} for server in inventory: t = server["type"] types[t] = types.get(t, 0) + 1 print(f"\nTotal servers: {len(inventory)}") print("\nBy type:") for t, count in types.items(): print(f" {t}: {count}") # Count by status running = sum(1 for s in inventory if s["status"] == "running") print(f"\nStatus:") print(f" Running: {running}") print(f" Stopped: {len(inventory) - running}") print("=" * 40) def main(): """Main menu loop.""" print("\n" + "=" * 40) print(" SERVER INVENTORY SYSTEM") print("=" * 40) inventory = load_inventory() while True: print("\n--- Main Menu ---") print("1. List all servers") print("2. Add server") print("3. Remove server") print("4. Search by type") print("5. Generate summary") print("6. Exit") choice = input("\nSelect option (1-6): ") if choice == "1": list_servers(inventory) elif choice == "2": add_server(inventory) elif choice == "3": remove_server(inventory) elif choice == "4": search_servers(inventory) elif choice == "5": generate_summary(inventory) elif choice == "6": print("\nGoodbye! šŸ‘‹") break else: print("\nāœ— Invalid option. Please choose 1-6.") if __name__ == "__main__": main()

šŸ“ Practice Exercises

  1. Create a to-do list application that saves tasks to a file
  2. Build a contact book using JSON storage
  3. Write a log file analyzer that counts different log levels
  4. Create a simple expense tracker with CSV export

šŸ’” DevOps Relevance

Why this matters:

  • Lists: Store server names, IPs, ports, commands
  • Dictionaries: Configuration, API responses, structured data
  • File I/O: Read configs, write logs, generate reports
  • JSON: API communication, configuration files, data exchange

āœ… Day 5 Checklist

  • Can create and manipulate lists
  • Know list comprehensions
  • Can work with dictionaries
  • Understand nested data structures
  • Can read and write files
  • Know how to use JSON
  • Completed mini project

šŸŽ‰ Week 1 Complete!

Congratulations! You've completed Python Foundations. You now have the programming skills needed for DevOps automation.

What you learned:

  • Python basics and syntax
  • Variables and data types
  • Control flow (conditions and loops)
  • Functions and code organization
  • Data structures (lists and dictionaries)
  • File operations and JSON

Next up: Week 2 - Linux + Networking Basics