In Python development, environment variables are a concept that is both important and easily overlooked. Whether configuring database connections, API keys, or distinguishing between development and production environments, environment variables play a crucial role. However, many developers' operations with environment variables remain at a basic level, lacking systematic understanding and practical skills.
This article will take you deep into the methods of reading environment variables in Python, from basic operations to advanced techniques, and then to practical project applications, allowing you to thoroughly master this important programming skill. Whether you are a Python beginner or an experienced developer, you can gain practical knowledge and best practices from this.
Environment variables are dynamic named values used in operating systems to store system configuration information. In Python development, we commonly use environment variables to:
In Windows systems, environment variables have the following characteristics:
The os module is the basic tool for handling environment variables in Python's standard library:
Pythonimport os
# Read environment variables
def get_env_basic():
# Method 1: Direct reading, will raise KeyError if not exists
try:
db_host = os.environ['DB_HOST']
print(f"Database Host: {db_host}")
except KeyError:
print("DB_HOST environment variable not set")
# Method 2: Use get method, provide default value
db_port = os.environ.get('DB_PORT', '3306')
print(f"Database Port: {db_port}")
# Method 3: Get all environment variables
all_env = os.environ
print(f"Total environment variables: {len(all_env)}")

For project development, it's recommended to use the python-dotenv library to manage environment variables:
Bashpip install python-dotenv
Create .env file:
text# Database configuration DB_HOST=127.0.0.1 DB_PORT=3306 DB_USER=admin DB_PASSWORD=secret123 # API configuration API_KEY=your_api_key_here DEBUG=True
Python code:
Pythonfrom dotenv import load_dotenv
import os
# Load .env file
load_dotenv()
class Config:
"""Configuration class for unified environment variable management"""
def __init__(self):
self.db_host = os.getenv('DB_HOST', 'localhost')
self.db_port = int(os.getenv('DB_PORT', 3306))
self.db_user = os.getenv('DB_USER', 'root')
self.db_password = os.getenv('DB_PASSWORD', '')
self.api_key = os.getenv('API_KEY', '')
self.debug = os.getenv('DEBUG', 'False').lower() == 'true'
def get_db_url(self):
"""Build database connection URL"""
return f"mysql://{self.db_user}:{self.db_password}@{self.db_host}:{self.db_port}/mydb"
def display_config(self):
"""Display configuration information (hide sensitive info)"""
print(f"Database Host: {self.db_host}")
print(f"Database Port: {self.db_port}")
print(f"API Key: {'*' * len(self.api_key) if self.api_key else 'Not Set'}")
print(f"Debug Mode: {self.debug}")
# Use configuration
config = Config()
config.display_config()

Environment variables are all string types, requiring type conversion for actual use:
Pythonimport os
from typing import Optional, Union
class EnvHelper:
"""Environment variable helper class"""
@staticmethod
def get_str(key: str, default: str = '') -> str:
"""Get string type environment variable"""
return os.getenv(key, default)
@staticmethod
def get_int(key: str, default: int = 0) -> int:
"""Get integer type environment variable"""
value = os.getenv(key)
if value is None:
return default
try:
return int(value)
except ValueError:
print(f"Warning: {key} is not a valid integer, using default value {default}")
return default
@staticmethod
def get_bool(key: str, default: bool = False) -> bool:
"""Get boolean type environment variable"""
value = os.getenv(key, '').lower()
if value in ('true', '1', 'yes', 'on'):
return True
elif value in ('false', '0', 'no', 'off'):
return False
else:
return default
@staticmethod
def get_list(key: str, separator: str = ',', default: list = None) -> list:
"""Get list type environment variable"""
if default is None:
default = []
value = os.getenv(key)
if value is None:
return default
return [item.strip() for item in value.split(separator) if item.strip()]
@staticmethod
def validate_required(required_vars: list) -> dict:
"""Validate whether required environment variables exist"""
missing = []
present = {}
for var in required_vars:
value = os.getenv(var)
if value is None:
missing.append(var)
else:
present[var] = value
if missing:
raise ValueError(f"Missing required environment variables: {', '.join(missing)}")
return present
# Usage example
if __name__ == "__main__":
# Type conversion example
port = EnvHelper.get_int('SERVER_PORT', 8080)
debug = EnvHelper.get_bool('DEBUG', False)
allowed_hosts = EnvHelper.get_list('ALLOWED_HOSTS', ',', ['localhost'])
driver_data = EnvHelper.get_str('DriverData', '')
print(f"Server Port: {port} (Type: {type(port)})")
print(f"Debug Mode: {debug} (Type: {type(debug)})")
print(f"Allowed Hosts: {allowed_hosts} (Type: {type(allowed_hosts)})")
print(f"Driver Data: {driver_data} (Type: {type(driver_data)})")
# Validate required variables
try:
required = EnvHelper.validate_required(['DB_HOST', 'API_KEY'])
print("All required variables are set")
except ValueError as e:
print(f"Configuration error: {e}")

Pythonimport os
from dotenv import load_dotenv
import mysql.connector
from mysql.connector import Error
load_dotenv()
class DatabaseManager:
"""Database management class"""
def __init__(self):
self.host = os.getenv('DB_HOST', 'localhost')
self.port = int(os.getenv('DB_PORT', 3306))
self.user = os.getenv('DB_USER', 'root')
self.password = os.getenv('DB_PASSWORD', '')
self.database = os.getenv('DB_NAME', 'test')
self.connection = None
def connect(self):
"""Establish database connection"""
try:
self.connection = mysql.connector.connect(
host=self.host,
port=self.port,
user=self.user,
password=self.password,
database=self.database
)
if self.connection.is_connected():
print(f"Successfully connected to MySQL database: {self.database}")
return True
except Error as e:
print(f"Database connection failed: {e}")
return False
def disconnect(self):
"""Disconnect database connection"""
if self.connection and self.connection.is_connected():
self.connection.close()
print("Database connection disconnected")
def execute_query(self, query: str):
"""Execute query"""
if not self.connection or not self.connection.is_connected():
print("Please establish database connection first")
return None
try:
cursor = self.connection.cursor()
cursor.execute(query)
result = cursor.fetchall()
cursor.close()
return result
except Error as e:
print(f"Query execution failed: {e}")
return None
# Usage example
db_manager = DatabaseManager()
if db_manager.connect():
# Execute query operations
results = db_manager.execute_query("SELECT VERSION()")
if results:
print(f"Database version: {results[0][0]}")
db_manager.disconnect()

Pythonimport os
from dotenv import load_dotenv
import json
from dataclasses import dataclass
from typing import Dict, Any
load_dotenv()
@dataclass
class SerialConfig:
"""Serial port configuration"""
port: str
baudrate: int
timeout: float
@classmethod
def from_env(cls):
return cls(
port=os.getenv('SERIAL_PORT', 'COM1'),
baudrate=int(os.getenv('SERIAL_BAUDRATE', 9600)),
timeout=float(os.getenv('SERIAL_TIMEOUT', 1.0))
)
@dataclass
class ModbusConfig:
"""Modbus configuration"""
host: str
port: int
slave_id: int
@classmethod
def from_env(cls):
return cls(
host=os.getenv('MODBUS_HOST', '192.168.1.100'),
port=int(os.getenv('MODBUS_PORT', 502)),
slave_id=int(os.getenv('MODBUS_SLAVE_ID', 1))
)
class HMIConfig:
"""HMI configuration management"""
def __init__(self):
self.serial = SerialConfig.from_env()
self.modbus = ModbusConfig.from_env()
self.scan_interval = float(os.getenv('SCAN_INTERVAL', 1.0))
self.log_level = os.getenv('LOG_LEVEL', 'INFO')
self.data_storage_path = os.getenv('DATA_STORAGE_PATH', './data')
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary format"""
return {
'serial': {
'port': self.serial.port,
'baudrate': self.serial.baudrate,
'timeout': self.serial.timeout
},
'modbus': {
'host': self.modbus.host,
'port': self.modbus.port,
'slave_id': self.modbus.slave_id
},
'scan_interval': self.scan_interval,
'log_level': self.log_level,
'data_storage_path': self.data_storage_path
}
def save_to_file(self, filename: str = 'config.json'):
"""Save configuration to file"""
with open(filename, 'w', encoding='utf-8') as f:
json.dump(self.to_dict(), f, indent=2, ensure_ascii=False)
print(f"Configuration saved to {filename}")
def display_config(self):
"""Display current configuration"""
print("=== HMI Configuration Information ===")
print(f"Serial Port: {self.serial.port}")
print(f"Baud Rate: {self.serial.baudrate}")
print(f"Modbus Host: {self.modbus.host}:{self.modbus.port}")
print(f"Slave ID: {self.modbus.slave_id}")
print(f"Scan Interval: {self.scan_interval} seconds")
print(f"Log Level: {self.log_level}")
print(f"Data Storage Path: {self.data_storage_path}")
# Usage example
if __name__ == "__main__":
config = HMIConfig()
config.display_config()
config.save_to_file()

Pythonimport os
import subprocess
import platform
class EnvManager:
"""Environment variable manager"""
@staticmethod
def set_env_var(key: str, value: str, permanent: bool = False):
"""Set environment variable"""
# Temporary setting (effective only for current process)
os.environ[key] = value
print(f"Temporary environment variable {key} set to: {value}")
# Permanent setting (Windows system)
if permanent and platform.system() == 'Windows':
try:
# Set user-level environment variable
subprocess.run([
'setx', key, value
], check=True, capture_output=True)
print(f"Permanent environment variable {key} has been set")
except subprocess.CalledProcessError as e:
print(f"Failed to set permanent environment variable: {e}")
@staticmethod
def delete_env_var(key: str):
"""Delete environment variable"""
if key in os.environ:
del os.environ[key]
print(f"Environment variable {key} deleted")
else:
print(f"Environment variable {key} does not exist")
@staticmethod
def backup_env_vars(keys: list, filename: str = 'env_backup.txt'):
"""Backup specified environment variables"""
backup_data = []
for key in keys:
value = os.getenv(key)
if value is not None:
backup_data.append(f"{key}={value}")
with open(filename, 'w', encoding='utf-8') as f:
f.write('\n'.join(backup_data))
print(f"Environment variables backed up to {filename}")
@staticmethod
def restore_env_vars(filename: str = 'env_backup.txt'):
"""Restore environment variables from backup file"""
try:
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if '=' in line:
key, value = line.split('=', 1)
os.environ[key] = value
print(f"Restored environment variable: {key}")
except FileNotFoundError:
print(f"Backup file {filename} does not exist")
except Exception as e:
print(f"Error occurred while restoring environment variables: {e}")
# Usage example
if __name__ == "__main__":
env_manager = EnvManager()
# Set environment variables
env_manager.set_env_var('MY_APP_VERSION', '1.0.0')
env_manager.set_env_var('MY_APP_DEBUG', 'true', permanent=True)
# Backup environment variables
env_manager.backup_env_vars(['MY_APP_VERSION', 'MY_APP_DEBUG'])
# Read set environment variables
print(f"Application Version: {os.getenv('MY_APP_VERSION')}")
print(f"Debug Mode: {os.getenv('MY_APP_DEBUG')}")

Through the in-depth explanation in this article, we have comprehensively mastered the skills of reading and managing environment variables in Python. Let's review three key points:
1. Flexible Application of Multiple Reading Methods: From basic os.environ to professional python-dotenv library, and then to custom type conversion tools, choosing appropriate methods for different scenarios can greatly improve development efficiency.
2. Type Conversion and Validation Cannot Be Ignored: Environment variables are essentially all strings, and in actual projects, appropriate type conversion and validation must be performed to ensure program robustness and reliability.
3. Practical Application is Key: Whether it's database connection management, HMI development configuration, or dynamic management of environment variables, mastering these practical skills can make your Python development more professional and efficient.
Environment variable management is a fundamental skill in modern software development. By mastering these techniques, you can write more flexible, secure, and maintainable Python applications. It is recommended to practice more in actual projects and deepen understanding by combining specific business scenarios.
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!