杰瑞科技汇

Python is settings,如何配置与管理?

Of course! That's an excellent question. The phrase "Python is settings" is a bit informal, but it gets to the heart of how Python applications are configured.

Python is settings,如何配置与管理?-图1
(图片来源网络,侵删)

In short, "Python is settings" refers to the practice of configuring a Python application's behavior through a dedicated configuration file or module, rather than hard-coding values directly into the source code.

This is a fundamental principle of writing clean, maintainable, and flexible software.

Let's break down why this is so important, the common patterns, and best practices.


The Problem with Hard-Coding

Imagine you have a simple web application:

Python is settings,如何配置与管理?-图2
(图片来源网络,侵删)
# app.py
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
    # This is BAD - the database URL is hard-coded!
    db_connection_string = "postgresql://user:password@localhost:5432/mydb"
    return {"message": f"Connecting to DB at {db_connection_string}"}
if __name__ == "__main__":
    # This port is also hard-coded!
    uvicorn.run(app, host="0.0.0.0", port=8000)

This code is difficult to manage for several reasons:

  • Environment Specificity: The database URL and port might be different on your local machine (localhost), your testing server, and your production server.
  • Security: You shouldn't commit database passwords or API keys to your version control (like Git).
  • Reusability: You can't easily run the same code on different ports or for different purposes without changing the code itself.
  • Collaboration: If another developer needs a different database, they have to modify the code, which can lead to conflicts.

The Solution: Externalizing Settings

The solution is to move all these "magic values" into a separate settings file or module. This is what "Python is settings" means in practice.

Here are the most common and effective ways to do this.

Method 1: The Classic settings.py File

This is the simplest approach. You create a dedicated Python file for your settings.

settings.py

# This file contains all the configuration for your application.
# App Settings
APP_NAME = "My Awesome App"
DEBUG = True
SECRET_KEY = "a-very-secret-key-that-you-should-change"
# Database Settings
DATABASE_URL = "postgresql://user:password@localhost:5432/mydb"
# Server Settings
HOST = "0.0.0.0"
PORT = 8000

app.py (Updated)

# app.py
import uvicorn
from fastapi import FastAPI
# Import the settings file
from settings import DATABASE_URL, HOST, PORT
app = FastAPI()
@app.get("/")
def read_root():
    # Now we use the variable from our settings file
    return {"message": f"Connecting to DB at {DATABASE_URL}"}
if __name__ == "__main__":
    # And use it here as well
    uvicorn.run(app, host=HOST, port=PORT)

Pros:

  • Simple and easy to understand.
  • Provides centralization for all configuration.

Cons:

  • Security Risk: You must add settings.py to your .gitignore file to avoid committing secrets. This can be forgotten.
  • Not ideal for managing different environments (dev, staging, prod).

Method 2: Using Environment Variables (The Modern Standard)

This is the most recommended approach for production applications. You store configuration values as environment variables on the machine where the code is running. Python libraries like python-dotenv make this easy.

Create a .env file for local development. .env

# Add this file to your .gitignore!
APP_NAME="My Awesome App"
DEBUG=True
SECRET_KEY="a-very-secret-key-that-you-should-change"
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
HOST="0.0.0.0"
PORT="8000"

Create a settings.py file that loads from the .env file. settings.py

from pydantic import BaseSettings, Field
class Settings(BaseSettings):
    """Application settings loaded from environment variables."""
    app_name: str = Field(default="My Awesome App", env="APP_NAME")
    debug: bool = Field(default=False, env="DEBUG")
    secret_key: str = Field(..., env="SECRET_KEY") # Ellipsis (...) means it's required
    database_url: str = Field(..., env="DATABASE_URL")
    host: str = Field(default="0.0.0.0", env="HOST")
    port: int = Field(default=8000, env="PORT")
    class Config:
        env_file = ".env" # Tells pydantic to read from .env
# Create a single instance to be imported by other modules
settings = Settings()

Update your application code. app.py (Updated with Pydantic)

# app.py
import uvicorn
from fastapi import FastAPI
# Import the settings instance
from settings import settings
app = FastAPI()
@app.get("/")
def read_root():
    # The settings object gives us type-hinted access to our variables
    return {"message": f"Connecting to DB at {settings.database_url}"}
if __name__ == "__main__":
    uvicorn.run(app, host=settings.host, port=settings.port)

Pros:

  • Secure: Secrets are never stored in your codebase.
  • Environment-Specific: You can have different .env files for different environments (e.g., .env.staging, .env.prod).
  • Standard Practice: This is the de-facto standard for modern containerized applications (Docker, Kubernetes).

Method 3: Using a Dedicated Library (e.g., Dynaconf)

For more complex applications, libraries like Dynaconf are fantastic. They can read from multiple sources in a specific order (e.g., .env files, environment variables, configuration files like TOML/JSON, secrets managers like AWS Secrets Manager).

settings.py with Dynaconf

# settings.py
from dynaconf import Dynaconf
# Dynaconf will automatically look for .toml, .yaml, .env, and environment variables
settings = Dynaconf(
    settings_files=['settings.toml', '.secrets.toml'], # Example of other config files
    environments=True, # Allows for [default], [development], [production] sections
    env_switcher="ENV_FOR_DYNACONF", # The environment variable to switch contexts
)
# You can access settings like this:
# settings.DEBUG
# settings.get("DATABASE_URL")

Pros:

  • Extremely flexible and powerful.
  • Supports multiple formats and sources.
  • Handles different environments seamlessly.

Summary: Best Practices

  1. NEVER hard-code configuration values (especially secrets) in your source code.
  2. Use a settings.py file to centralize your configuration logic.
  3. Use a BaseSettings class from Pydantic or a library like Dynaconf to load your settings. This gives you type-hinting and validation for free.
  4. Store secrets in environment variables or a secrets manager. Use a .env file for local development.
  5. Add .env and any secret files to your .gitignore.
  6. Document your settings so other developers (or your future self) know what they are and how to use them.

By following these principles, you make your Python applications more secure, robust, and easier to manage across different environments.

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