杰瑞科技汇

Python configutil如何读写配置文件?

Of course! "Configutil" isn't a standard, built-in Python library like json or os. It's a common term for a utility or a set of functions designed to manage configuration files.

Python configutil如何读写配置文件?-图1
(图片来源网络,侵删)

Since there's no single "configutil" module, I'll show you the best ways to handle configuration in Python, from the simplest built-in methods to powerful, dedicated libraries. This guide will cover:

  1. Using Standard Libraries (configparser, json, toml, yaml): The "Pythonic" way.
  2. Creating Your Own configutil: A simple, reusable class for your projects.
  3. Using Dedicated Libraries: The professional, robust way.

The Pythonic Way: Standard Libraries

For most cases, Python's standard library has everything you need. The key is to choose the right file format for your needs.

a) .ini / .cfg Files with configparser

Perfect for simple, key-value pair configurations, often used in applications with sections (like [database], [server]).

File: config.ini

[database]
host = localhost
port = 5432
user = admin
password = secret
[server]
host = 0.0.0.0
port = 8080
debug = True

Python Code:

import configparser
# Create a config parser object
config = configparser.ConfigParser()
# Read the config file
config.read('config.ini')
# Access values
# Note: All values are read as strings by default.
# You need to cast them to the correct type.
db_host = config['database']['host']
db_port = int(config['database']['port'])
db_user = config['database']['user']
db_password = config['database']['password']
server_host = config['server']['host']
server_port = int(config['server']['port'])
# Use getboolean for boolean values
server_debug = config['server'].getboolean('debug')
print(f"Connecting to DB at {db_host}:{db_port} as {db_user}")
print(f"Server running on {server_host}:{server_port} with debug={server_debug}")
# You can also write to the config file
config['server']['port'] = '9000'
with open('config.ini', 'w') as configfile:
    config.write(configfile)

b) JSON Files with json

Excellent for structured data, APIs, and configurations that might be complex or nested. It's universally understood.

File: config.json

{
  "database": {
    "host": "localhost",
    "port": 5432,
    "user": "admin",
    "password": "secret"
  },
  "api_keys": {
    "google": "YOUR_GOOGLE_API_KEY",
    "openai": "YOUR_OPENAI_API_KEY"
  },
  "feature_flags": {
    "new_dashboard": true,
    "beta_access": false
  }
}

Python Code:

import json
# Read the JSON file
with open('config.json', 'r') as f:
    config = json.load(f)
# Access values
db_host = config['database']['host']
api_key = config['api_keys']['google']
new_dashboard_enabled = config['feature_flags']['new_dashboard']
print(f"Google API Key: {api_key}")
print(f"New Dashboard Enabled: {new_dashboard_enabled}")
# Write to the JSON file (useful for updates)
config['feature_flags']['beta_access'] = True
with open('config.json', 'w') as f:
    json.dump(config, f, indent=4) # indent makes it pretty

c) TOML Files with toml (requires pip install toml)

TOML is a modern, human-readable config format. It's becoming very popular (used by projects like Rust's Cargo and Python's Poetry). It's stricter than JSON and great for files that will be edited by humans.

File: config.toml

[database]
host = "localhost"
port = 5432
[api_keys]
google = "YOUR_GOOGLE_API_KEY"
[feature_flags]
new_dashboard = true

Python Code:

# First, install the library: pip install toml
import toml
# Read the TOML file
config = toml.load('config.toml')
# Access values (they are parsed into correct Python types)
db_port = config['database']['port'] # This is an integer
google_key = config['api_keys']['google']
new_dashboard = config['feature_flags']['new_dashboard'] # This is a boolean
print(f"DB Port: {db_port} (type: {type(db_port)})")
print(f"New Dashboard: {new_dashboard} (type: {type(new_dashboard)})")

d) YAML Files with PyYAML (requires pip install pyyaml)

YAML is great for complex, nested configurations and is very human-readable. It's a superset of JSON, so it's more flexible.

File: config.yaml

database:
  host: localhost
  port: 5432
  user: admin
  password: secret
feature_flags:
  new_dashboard: true
  beta_access: false

Python Code:

# First, install the library: pip install pyyaml
import yaml
# Read the YAML file
with open('config.yaml', 'r') as f:
    config = yaml.safe_load(f)
# Access values
db_host = config['database']['host']
beta_access = config['feature_flags']['beta_access']
print(f"DB Host: {db_host}")
print(f"Beta Access: {beta_access}")

Creating Your Own configutil Class

If you want a simple, reusable utility that handles multiple file formats and provides a consistent interface, you can build your own.

This example will support JSON and TOML.

# configutil.py
import json
import toml
class ConfigUtil:
    """
    A simple configuration utility to load and save config files
    in JSON or TOML format.
    """
    def __init__(self, filepath):
        self.filepath = filepath
        self.config = {}
    def load(self):
        """Loads the configuration from the file."""
        try:
            if self.filepath.endswith('.json'):
                with open(self.filepath, 'r') as f:
                    self.config = json.load(f)
            elif self.filepath.endswith('.toml'):
                self.config = toml.load(self.filepath)
            else:
                raise ValueError("Unsupported file format. Use .json or .toml")
        except FileNotFoundError:
            print(f"Warning: Config file '{self.filepath}' not found. Using empty config.")
            self.config = {}
        return self.config
    def get(self, key, default=None):
        """Gets a value from the config using dot notation (e.g., 'database.host')."""
        keys = key.split('.')
        value = self.config
        try:
            for k in keys:
                value = value[k]
            return value
        except (KeyError, TypeError):
            return default
    def set(self, key, value):
        """Sets a value in the config using dot notation."""
        keys = key.split('.')
        config = self.config
        for k in keys[:-1]:
            config = config.setdefault(k, {})
        config[keys[-1]] = value
    def save(self):
        """Saves the configuration to the file."""
        if self.filepath.endswith('.json'):
            with open(self.filepath, 'w') as f:
                json.dump(self.config, f, indent=4)
        elif self.filepath.endswith('.toml'):
            with open(self.filepath, 'w') as f:
                toml.dump(self.config, f)
        else:
            raise ValueError("Unsupported file format for saving.")
# --- How to use your custom configutil ---
# 1. Create a config file (e.g., my_app.toml)
# [database]
# host = "127.0.0.1"
# port = 3306
# [logging]
# level = "INFO"
# file = "app.log"
# 2. Use the class in your application
if __name__ == "__main__":
    # Load the config
    config = ConfigUtil('my_app.toml')
    settings = config.load()
    # Get values safely
    db_host = config.get('database.host', 'localhost') # Returns '127.0.0.1'
    db_port = config.get('database.port') # Returns 3306
    log_level = config.get('logging.level') # Returns 'INFO'
    # This key doesn't exist, so it returns the default
    cache_size = config.get('cache.size', 100)
    print(f"DB Host: {db_host}")
    print(f"Cache Size: {cache_size}")
    # Update a value and save
    config.set('logging.level', 'DEBUG')
    config.set('new_feature.enabled', True)
    config.save()
    print("\nConfig updated and saved.")

Using Dedicated Libraries (The Professional Way)

For large, complex applications, or when you need features like environment variable overrides, validation, and secrets management, dedicated libraries are the best choice.

a) pydantic-settings

This is the modern standard for Python applications. It integrates pydantic for data validation and python-dotenv for environment variable management. It's incredibly powerful.

Installation: pip install pydantic-settings python-dotenv

File: .env (for secrets and local overrides)

DB_USER=my_local_user
DB_PASSWORD=super_secret_local_password

File: config.py (using pydantic-settings)

from pydantic import BaseSettings, Field
from typing import Optional
class Settings(BaseSettings):
    # It will automatically look for .env file and environment variables
    app_name: str = "My Awesome App"
    debug: bool = False
    # Nested settings are supported
    class Database(BaseSettings):
        host: str = Field(default="localhost", env="DB_HOST")
        port: int = Field(default=5432, env="DB_PORT")
        user: str = Field(..., env="DB_USER") # ... means it's required
        password: str = Field(..., env="DB_PASSWORD")
    database: Database = Database()
    # You can also have lists
    allowed_hosts: list[str] = ["localhost", "127.0.0.1"]
    class Config:
        env_file = ".env" # Specifies the .env file to use
        env_nested_delimiter = '_' # Allows DB_HOST via database.host
# Create a single instance to be imported across your app
settings = Settings()
# --- Usage ---
if __name__ == "__main__":
    print(f"App Name: {settings.app_name}")
    print(f"Debug Mode: {settings.debug}")
    print(f"Connecting to DB at {settings.database.host}:{settings.database.port} as {settings.database.user}")
    print(f"Allowed Hosts: {settings.allowed_hosts}")

b) dynaconf

Another excellent, feature-rich library that supports multiple file formats (.toml, .yaml, .json, .ini), environment variables, and secrets. It's very flexible.

Installation: pip install dynaconf

File: settings.toml

[default]
app_name = "My Awesome App"
debug = false
[default.database]
host = "localhost"
port = 5432
[development]
debug = true
[production]
database.host = "prod-db.internal"

Python Code:

from dynaconf import Dynaconf
# Dynaconf automatically finds settings.toml, .secrets.toml, .env files
settings = Dynaconf(
    settings_files=['settings.toml'],
    environments=True, # Allows [development], [production] etc.
    load_dotenv=True, # Loads .env files
)
# --- Usage ---
# Accessing values
print(f"App Name: {settings.app_name}")
print(f"Debug Mode: {settings.debug}")
# Switching environments (e.g., via an environment variable)
# export ENV_FOR_DYNACONF=development
print(f"Current Environment: {settings.current_env}")
print(f"Debug Mode in {settings.current_env}: {settings.debug}") # Will be True
# Accessing nested values
print(f"DB Host: {settings.database.host}")

Summary: Which One to Choose?

Method Best For Pros Cons
Standard Libraries Simple scripts, small projects, quick prototypes. No extra dependencies, built-in, simple. Manual type casting, no validation, less flexible for complex configs.
Custom configutil Medium-sized projects, custom needs, learning exercise. Full control, reusable, consistent interface. You have to build and maintain it yourself.
pydantic-settings Modern Python applications. The recommended choice. Automatic validation, type hints, secrets management, environment overrides. Requires pydantic and python-dotenv (but they are standard now).
dynaconf Complex projects, need for multiple formats/environments. Extremely flexible, many features, great for different deployment environments. Can be overkill for very simple needs.

For any serious project, I highly recommend starting with pydantic-settings. It provides the best combination of modern features, type safety, and ease of use.

分享:
扫描分享到社交APP
上一篇
下一篇