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
- Create a to-do list application that saves tasks to a file
- Build a contact book using JSON storage
- Write a log file analyzer that counts different log levels
- 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