Lab 1: The “Log Parser” (String to Int) Scenario: You read a response time from a log file, but it has “ms” at the end.
raw_time = "200ms"
# Step 1: Clean the data (Remove 'ms')
clean_time_str = raw_time.replace("ms", "")
# Step 2: Cast to Integer
time_int = int(clean_time_str)
# Step 3: Logic
if time_int > 100:
print("Alert: Latency is high!")
Lab 2: The Data Loss Experiment (Float to Int)
pi = 3.14159
gravity = 9.8
# Implicit (No data loss)
combined = pi + gravity
print(f"Implicit Sum: {combined}") # 12.94159
# Explicit (Data loss)
truncated_pi = int(pi)
print(f"Integer Pi: {truncated_pi}") # 3 (Decimal lost)
Lab 3: The “Env Var” List Parser (String $\rightarrow$ List)
Scenario: You are configuring a firewall script. The allowed IP addresses are passed as a single Environment Variable string (e.g., "10.0.0.1,10.0.0.2").
- The Trap: If you use
list(), it splits the string into individual characters! - The Fix: You must use the
.split()string method to create a list of items.
import os
# Simulating an Environment Variable
# format: "IP1,IP2,IP3"
env_allowed_ips = "192.168.1.10,192.168.1.20,10.5.5.1"
# --- WRONG WAY (Casting) ---
# This breaks the string into characters: ['1', '9', '2', ...]
wrong_list = list(env_allowed_ips)
print(f"Wrong List size: {len(wrong_list)}") # Output: 34 (Huge list of chars!)
# --- CORRECT WAY (Splitting) ---
# This splits the string at every comma
correct_list = env_allowed_ips.split(",")
print(f"Correct List: {correct_list}")
# Output: ['192.168.1.10', '192.168.1.20', '10.5.5.1']
# Architect Bonus: Clean up spaces just in case "IP, IP" was used
cleaned_list = [ip.strip() for ip in correct_list]
- Architect Insight:
list()constructor is for iterables (things you can loop over)..split()is for separators. Don’t confuse them!
Lab 4: The “Legacy API” Fixer (Bulk Conversion)
Scenario: You are consuming an old legacy API that returns everything as strings, even numbers and booleans. You need to sanitize this data before storing it in your modern database.
# The messy data from the old API
legacy_payload = {
"server_id": "9901",
"is_active": "true", # Lowercase string
"cpu_load": "45.5",
"tags": "web,prod,aws"
}
# The Sanitizer Logic
cleaned_data = {
# 1. Cast String to Integer
"id": int(legacy_payload["server_id"]),
# 2. Compare String to Boolean (Safest way)
"active": legacy_payload["is_active"].lower() == "true",
# 3. Cast String to Float
"load": float(legacy_payload["cpu_load"]),
# 4. Split String to List
"tags": legacy_payload["tags"].split(",")
}
print("Sanitized Data Schema:")
print(cleaned_data)
# Output: {'id': 9901, 'active': True, 'load': 45.5, 'tags': ['web', 'prod', 'aws']}
Lab 5: The “Hash Handler” (Bytes $\rightarrow$ Hex String)
Scenario: You are generating a SHA-256 checksum for a file to verify its integrity.
- The Challenge: Hashing libraries return bytes (binary data like
b'\xea\x98...'). You cannot print this effectively or save it to a text report. - The Fix: You must convert (decode) the bytes into a Hexadecimal String.
import hashlib
data = "MySecurePassword123"
# Step 1: Encode String to Bytes (Computers need bytes for math)
data_bytes = data.encode("utf-8")
# Step 2: Generate Hash (Returns binary object)
hash_object = hashlib.sha256(data_bytes)
binary_hash = hash_object.digest()
print(f"Raw Binary: {binary_hash}")
# Output: b'...' (Unreadable garbage characters)
# Step 3: Convert to Hex String (The "DevOps" way)
# .hexdigest() handles the casting from bytes to hex string automatically
readable_hash = hash_object.hexdigest()
print(f"Readable Hash: {readable_hash}")
# Output: 9f86d081884c7d659... (Standard readable hash)
- Architect Insight: In Security Automation, you will constantly convert between String (
utf-8) and Bytes (b''). Remember:str.encode()$\rightarrow$ Bytes,bytes.decode()$\rightarrow$ String.
Lab 6: Robust Safe-Casting Function
Scenario: You are building a utility library for your team. You want a function to_int that never crashes your script, even if the input is garbage.
def safe_int_cast(value, default=0):
"""
Tries to convert value to int.
If it fails (None, text, etc.), returns the default value.
"""
try:
# Handle cases where input is purely None
if value is None:
return default
# Try to cast
return int(float(value)) # Using float first handles "5.5" string cases
except (ValueError, TypeError):
print(f"Warning: Could not cast '{value}'. Using default.")
return default
# Test Cases
print(safe_int_cast("100")) # 100
print(safe_int_cast("50.99")) # 50 (Truncated)
print(safe_int_cast("NotNumber")) # 0 (Default, warning printed)
print(safe_int_cast(None)) # 0 (Default)
- Architect Insight: Writing “Wrapper Functions” like this is a hallmark of a Senior Developer. It makes your main code clean and error-proof.
Lab 7: The “Octal” Permission Trap
Scenario: You are setting file permissions (chmod). Linux permissions like 0777 are Octal numbers, not Decimals.
- The Trap:
int("0777")converts it to Decimal777. This is wrong foros.chmod! - The Fix: Tell
int()the base.
permission_str = "0755"
# WRONG: Default is base 10
wrong_perm = int(permission_str)
print(f"Base 10 Value: {wrong_perm}") # 755 (Decimal)
# CORRECT: Base 8 (Octal)
# This is what Linux expects for permissions
correct_perm = int(permission_str, 8)
print(f"Base 8 Value: {correct_perm}") # 493 (Decimal equivalent of 0o755)
# Proof using Python's oct() display
print(f"Octal Display: {oct(correct_perm)}") # 0o755