Hone logo
Hone
Problems

Robust Environment Management with Python

This challenge focuses on building a simple, yet effective, environment management system in Python. The goal is to create a tool that can load environment variables from a file (e.g., .env) and make them accessible in your Python code, while gracefully handling missing variables and providing a way to override them with system environment variables. This is crucial for managing configuration settings, API keys, and other sensitive information separately from your codebase.

Problem Description

You are tasked with creating a Python class called EnvironmentManager that handles loading and accessing environment variables. The class should:

  1. Load from File: Load environment variables from a specified .env file. Each line in the file should be in the format KEY=VALUE.
  2. Override with System Variables: If an environment variable with the same name already exists in the system environment, it should take precedence over the value loaded from the .env file.
  3. Handle Missing Variables: If a variable is requested that doesn't exist in either the .env file or the system environment, the class should return None.
  4. Provide a Getter Method: Offer a method get(key) to retrieve the value of a specific environment variable.
  5. Error Handling: Gracefully handle cases where the .env file does not exist or is malformed (e.g., a line doesn't contain an equals sign). In these cases, log an error message to the console and continue loading any valid variables.

Expected Behavior:

The EnvironmentManager should initialize by attempting to load variables from a .env file (defaulting to .env in the current directory if no file path is provided). It should then allow you to retrieve environment variables using the get(key) method. The system environment should always take precedence.

Examples

Example 1:

.env file:
API_KEY=your_api_key
DATABASE_URL=localhost:5432

System Environment:
DATABASE_URL=remote_db:8000

Code:
env_manager = EnvironmentManager()
api_key = env_manager.get("API_KEY")
database_url = env_manager.get("DATABASE_URL")

print(api_key)
print(database_url)

Output:

your_api_key
remote_db:8000

Explanation: The API_KEY is loaded from the .env file, while DATABASE_URL is overridden by the system environment variable.

Example 2:

.env file:
DEBUG=True

System Environment:
(No relevant variables set)

Code:
env_manager = EnvironmentManager()
debug_mode = env_manager.get("DEBUG")
missing_var = env_manager.get("NON_EXISTENT_VAR")

print(debug_mode)
print(missing_var)

Output:

True
None

Explanation: DEBUG is loaded from the .env file. NON_EXISTENT_VAR is not found and returns None.

Example 3: (Malformed .env file)

.env file:
API_KEY=your_api_key
INVALID_LINE
DATABASE_URL=localhost:5432

Code:
env_manager = EnvironmentManager()
api_key = env_manager.get("API_KEY")
database_url = env_manager.get("DATABASE_URL")

Output (to console):

Error: Invalid line in .env file: INVALID_LINE

Output (printed to standard output):

your_api_key
localhost:5432

Explanation: The malformed line is logged as an error, but the valid variables are still loaded.

Constraints

  • The .env file will be a plain text file.
  • Keys and values in the .env file will be strings.
  • The file path to the .env file can be a relative or absolute path.
  • The get() method should return None if the variable is not found.
  • Error messages should be printed to standard error (console).
  • The code should be reasonably efficient for typical .env file sizes (less than 1KB).

Notes

  • Consider using Python's built-in os module to access system environment variables.
  • You can use string manipulation techniques to parse the .env file.
  • Think about how to handle potential errors during file reading and parsing.
  • The class should be designed to be reusable and easy to integrate into other Python projects.
  • No external libraries are allowed for this challenge (e.g., python-dotenv). The goal is to implement the environment loading logic yourself.
Loading editor...
python