REW

How Do I Import Configuration Into Python?

Published Aug 29, 2025 5 min read
On this page

The following is an extensive article on importing configuration into Python, covering various methods and best practices.

Importing Configuration in Python

Efficiently managing configuration is a fundamental aspect of building robust, maintainable, and scalable Python applications. Instead of hard-coding values like database credentials, API keys, or directory paths, developers separate them into configuration files. This separation allows applications to adapt to different environments (e.g., development, testing, and production) without changing the core codebase.

This article explores the most common and effective methods for importing configuration into Python, from simple module imports to using specialized libraries and environment variables.

Method 1: The simple Python file

For smaller applications, the simplest method is to use a plain Python file to store configuration. This approach is straightforward and requires no external libraries.

How it works:

  1. Create a config.py file with all your settings.
  2. Import this file into your application code like any other Python module.

Example: config.py

# config.py
DATABASE_URL = "postgres://user:password@localhost:5432/mydatabase"
API_KEY = "your_dev_api_key_here"
DEBUG_MODE = True

Use code with caution.

Example: app.py

# app.py
import config
if config.DEBUG_MODE:
    print("Running in debug mode.")
print(f"Connecting to database: {config.DATABASE_URL}")

Use code with caution.

Pros:

  • Simple: No extra dependencies are needed.
  • Pythonic: Configuration is defined using standard Python syntax.
  • Expressive: Supports any Python data structure (lists, dictionaries, classes).

Cons:

  • Security risk: If sensitive data like passwords are in config.py and committed to version control, it can be exposed.
  • Limited flexibility: Not ideal for different environments without manual changes or branching.

Method 2: The configparser module

The built-in configparser module is a powerful tool for handling configurations stored in INI-style files. This is a standard and human-readable format, making it easy for non-developers to edit.

How it works:

  1. Create a .ini file with sections and key-value pairs.
  2. Use the configparser library to read and access the settings.

Example: config.ini

[DEVELOPMENT]
DATABASE_URL = postgres://user:password@localhost:5432/dev_db
API_KEY = dev_api_key
[PRODUCTION]
DATABASE_URL = postgres://prod_user:prod_password@prod_server:5432/prod_db
API_KEY = prod_api_key

Use code with caution.

Example: app.py

# app.py
import configparser
config = configparser.ConfigParser()
config.read('config.ini')
# Let's assume we are in development for this example
env = 'DEVELOPMENT'
db_url = config[env]['DATABASE_URL']
api_key = config[env]['API_KEY']
print(f"Environment: {env}")
print(f"Database URL: {db_url}")

Use code with caution.

Pros:

  • Standard Library: No installation required.
  • Structured: Uses sections and key-value pairs for organization.
  • Type Casting: Supports convenient methods like getint(), getfloat(), and getboolean().
  • Interpolation: Allows values to reference other values within the file.

Cons:

  • Limited data types: Does not natively support nested structures like lists or dictionaries without manual parsing.

Method 3: YAML and JSON files

For more complex configuration that requires nested data structures, JSON and YAML are excellent choices. YAML, in particular, is valued for its human-readable syntax.

How it works:

  1. Create a .json or .yaml file.
  2. Use the built-in json module or the third-party PyYAML library to load the data.

Example: config.yaml

database:
  host: localhost
  port: 5432
  user: dev_user
  password: dev_password
api:
  key: your_dev_api_key

Use code with caution.

Example: app.py

# app.py
import yaml
with open('config.yaml', 'r') as f:
    config = yaml.safe_load(f)
db_host = config['database']['host']
api_key = config['api']['key']
print(f"Database host: {db_host}")
print(f"API key: {api_key}")

Use code with caution.

Pros:

  • Supports complex data: Natively handles nested lists and dictionaries.
  • Widely used: JSON is a universal data format, while YAML is very popular for configuration files.

Cons:

  • Requires external libraries (for YAML): The PyYAML library needs to be installed (pip install PyYAML).
  • Less intuitive for non-developers (JSON): JSON's strict syntax can be less user-friendly than INI or YAML.

Method 4: Environment variables and python-dotenv

This method is crucial for applications following the "Twelve-Factor App" methodology, which dictates that configuration should be stored in the environment. It is the most secure way to handle secrets and is especially common in web development and containerized applications.

How it works:

  1. Create a .env file in the root of your project to hold key-value pairs for local development. Crucially, add .env to your .gitignore file to prevent sensitive data from being committed.
  2. Install the python-dotenv library: pip install python-dotenv.
  3. Use load_dotenv() to load variables from the .env file into the environment.
  4. Access the variables using Python's built-in os module.

Example: .env

DATABASE_URL=postgres://user:password@localhost:5432/mydatabase
SECRET_KEY=my_development_secret_key

Use code with caution.

Example: app.py

# app.py
import os
from dotenv import load_dotenv
load_dotenv() # Load variables from .env file
db_url = os.getenv("DATABASE_URL")
secret_key = os.getenv("SECRET_KEY")
print(f"DB URL: {db_url}")
print(f"Secret Key: {secret_key}")

Use code with caution.

Pros:

  • Secure: Keeps secrets out of codebase and version control.
  • Best practice: Aligns with modern application standards.
  • Flexible: Easily change configuration across different environments.

Cons:

  • Requires extra library: Needs python-dotenv.
  • Development file management: Developers must manage a separate .env and exclude it from Git.

Advanced configuration loading strategies

More sophisticated configuration management is often needed as applications grow. A common strategy is to use a layered approach, combining multiple methods with a specific order of priority. This typically involves loading defaults, then overriding them with settings from configuration files, and finally applying overrides from environment variables, which take the highest precedence.

An example implementation of a layered approach is shown in the config_loader.py code provided in the original text, which demonstrates loading defaults, then reading from an INI file (potentially environment-specific like config.dev.ini), and finally using environment variables to override settings. The full code for this example can be found in the referenced web documents.

Tips for robust configuration management

  • Single point of access: Load configuration once at application startup and pass it where needed.
  • Schema validation: Use libraries like Pydantic or jsonschema to validate configuration format and data types.
  • Separate files for environments: Use distinct configuration files for different environments (e.g., development, production).
  • Document everything: Add comments to configuration files and code to clarify settings.
Enjoyed this article? Share it with a friend.