Day 5 | Command Line Arguments & Environment Variables in Python
This chapter covers the transition from writing static, hardcoded scripts to building dynamic, production-ready DevOps automation tools. We will explore how to accept external inputs using command-line arguments and how to securely manage sensitive configuration data using environment variables.
1. The Problem of Hardcoded Values
In basic scripts, input parameters are often hardcoded directly into the source code. For example, a basic calculator script might define static variables for its operations:
# Naive approach: Hardcoded values
def add(num1, num2):
return num1 + num2
# Static inputs
number1 = 5
number2 = 10
result = add(number1, number2)
print(f"Addition of {number1} + {number2} is {result}")
Why This Fails in Production
- Lack of Reusability: Every time a user wants to calculate a different set of numbers, they must open the source code, modify the file, save it, and re-run it.
- Security Risks: Hardcoding configuration details, credentials, or API keys directly into the source code exposes sensitive data to anyone with read access to the repository.
- Automation Roadblocks: Automated systems (such as CI/CD pipelines or cron jobs) cannot interactively edit source files to pass dynamic values during execution.
2. The Core Mental Model: Dynamic Inputs
To make scripts robust and reusable, we must decouple the execution logic from the input data. Instead of modifying the code, users should pass inputs from the outside during execution.
User Input (Terminal)
|
| passes "2", "add", "3"
v
Python Script (calculator.py)
|
| processes inputs dynamically
v
Output (5.0)
By accepting external inputs, the same script can handle infinite variations of data without requiring a single line of code modification.
3. Understanding Command Line Arguments (CLI Args)
Command-line arguments are parameters passed to a script at the moment of execution. Instead of running a script statically as python calculator.py, you append inputs directly after the filename:
python calculator.py 2 add 3
Here, 2, add, and 3 are command-line arguments passed directly into the execution context of calculator.py.
4. Real-World Analogy: AWS CLI
If you have used the AWS Command Line Interface (AWS CLI), you have already used command-line arguments. Under the hood, the AWS CLI is a Python application.
When you execute:
aws s3 ls
You are executing a Python program (aws) and passing two command-line arguments to it:
s3(specifying the service)ls(specifying the action/operation)
The program reads these arguments dynamically to determine which API call to make to the AWS cloud.
5. Step-by-Step Implementation: The sys Module
Python provides several built-in modules to handle command-line arguments. The most fundamental is the sys (System) module. Because sys is an inbuilt module, it is bundled with your standard Python installation; you do not need to install it via pip. However, you must still explicitly import it into your script.
The sys.argv List
The sys module exposes a list called argv (argument vector) that automatically captures all command-line inputs.
sys.argv[0]always contains the name of the script itself (calculator.py).sys.argv[1]contains the first user-provided argument (2).sys.argv[2]contains the second argument (add).sys.argv[3]contains the third argument (3).
Naive CLI Implementation (With a Hidden Bug)
import sys
# Reading command line arguments
num1 = sys.argv[1]
operation = sys.argv[2]
num2 = sys.argv[3]
def add(n1, n2):
return n1 + n2
if operation == "add":
output = add(num1, num2)
print(output)
If you run this script with python calculator.py 2 add 3, the output is unexpected:
Output: 23
6. The String Concatenation Trap & Type Casting
The output of 23 instead of 5 occurs because all command-line arguments read via sys.argv are treated as strings by default.
When Python executes add("2", "3"), it performs string concatenation rather than mathematical addition:
The Solution: Type Casting
To perform mathematical operations, you must explicitly cast the string inputs into numeric types (int or float). Using float is preferred for calculators to support decimal values.
import sys
# Explicitly cast string inputs to float
num1 = float(sys.argv[1])
operation = sys.argv[2]
num2 = float(sys.argv[3])
def add(n1, n2):
return n1 + n2
def sub(n1, n2):
return n1 - n2
if operation == "add":
output = add(num1, num2)
print(f"Result: {output}")
elif operation == "sub":
output = sub(num1, num2)
print(f"Result: {output}")
Now, executing python calculator.py 2.5 add 3.5 yields the correct mathematical output:
Result: 6.0
7. Environment Variables: Protecting Sensitive Data
While command-line arguments are excellent for non-sensitive inputs (like numbers or operation types), they are highly insecure for sensitive information such as:
- API Keys
- Database Passwords
- Authentication Tokens
- TLS Certificates
Why CLI Arguments Fail for Secrets
- Shell History: Any argument typed directly into the terminal is saved in plain text in your shell history file (e.g.,
~/.bash_historyor~/.zsh_history). - Process Visibility: Other users on the same Linux system can view running processes and their command-line arguments using commands like
ps -ef. - CI/CD Logs: Hardcoding or passing secrets as CLI arguments in CI/CD configuration files (like Jenkinsfiles or GitHub Actions YAMLs) exposes them in build logs and version control.
The Solution: Environment Variables (Env Vars)
Environment variables are key-value pairs maintained by the operating system's shell environment. They exist outside the application code and can be read dynamically by running processes.
8. Command Line Args vs. Environment Variables
9. Step-by-Step Implementation: The os Module
To interact with the operating system and read environment variables in Python, we use the built-in os module.
Setting an Environment Variable in the Terminal
Before running your Python script, export the variable in your terminal session:
# On Linux / macOS
export API_TOKEN="prod-secret-token-9988"
export DB_PASSWORD="super-secure-password"
Reading Environment Variables in Python
Use the os.getenv() function to retrieve the value of the environment variable.
import os
# Retrieve the environment variables
api_token = os.getenv("API_TOKEN")
db_password = os.getenv("DB_PASSWORD")
# Print the values to verify (Avoid printing secrets in production!)
print(f"Retrieved Token: {api_token}")
print(f"Retrieved Password: {db_password}")
If you execute this script, Python reads the values directly from the shell environment:
Retrieved Token: prod-secret-token-9988
Retrieved Password: super-secure-password
Note: If an environment variable is not set,
os.getenv()returnsNoneby default without crashing the program. This makes it safer than accessingos.environ["VAR_NAME"]directly, which raises aKeyErrorif the variable is missing.
10. CI/CD & DevOps Production Use Cases
In modern DevOps workflows, environment variables are the industry standard for configuration management and security.
[GitHub Secrets / HashiCorp Vault]
|
| injects secrets securely
v
[Jenkins / CI Runner] (Environment Variables)
|
| executes script
v
[Python Automation Script] (os.getenv)
Scenario: Automating Cloud Infrastructure
When running an automation script inside a Jenkins runner, GitHub Actions runner, or a Kubernetes Pod:
- The CI/CD platform securely injects credentials (like
AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEY) into the runner's environment. - The Python script executes simply as:
BASH
python deploy.py - Inside
deploy.py, the script reads the credentials usingos.getenv()to authenticate with cloud APIs. - No passwords or tokens are exposed in the source code repository or the CI/CD pipeline configuration files.
11. Summary and Key Takeaways
- Decouple Code and Data: Hardcoding values makes scripts rigid and insecure. Always pass dynamic inputs externally.
- Command-Line Arguments: Use
sys.argvto pass non-sensitive execution parameters directly from the terminal. - Argument Indexing:
sys.argv[0]is always the script name. User arguments begin at index1. - Type Casting is Mandatory: All command-line arguments are read as strings. Convert them to
intorfloatbefore performing mathematical operations. - Environment Variables for Secrets: Never pass sensitive data like API keys, passwords, or tokens via command-line arguments. Use environment variables instead.
- The
osModule: Useos.getenv("VARIABLE_NAME")to safely retrieve environment variables in Python without risking runtime crashes. - Production Standard: Combining CLI arguments for configuration and environment variables for secrets is the standard pattern for writing secure, robust, and automated DevOps scripts.