You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Python程序配置互斥输入源的配置文件结构?

互斥数据源配置的最佳实践:策略模式+结构化配置

一、结构化配置设计(基于dataclass)

针对互斥数据源场景,我们可以用typing.Union标记互斥的配置类,同时添加类型标识字段区分数据源类型,既保证配置结构化,又能清晰识别要使用的数据源。

示例代码

from dataclasses import dataclass
from typing import Union, Optional

# 通用基础配置
@dataclass
class BaseConfig:
    output_path: str
    chunk_size: int = 1000

# CSV专属配置
@dataclass
class CSVConfig:
    type: str = "csv"
    file_path: str
    delimiter: str = ","
    encoding: str = "utf-8"

# 数据库专属配置
@dataclass
class DBConfig:
    type: str = "db"
    host: str
    port: int
    database: str
    username: str
    password: str
    query: str

# 总配置:基础配置 + 互斥数据源配置
@dataclass
class AppConfig:
    base: BaseConfig
    source: Union[CSVConfig, DBConfig]

配置文件示例(JSON格式,标准库可直接解析)

CSV版本:

{
    "base": {
        "output_path": "./processed_data",
        "chunk_size": 2000
    },
    "source": {
        "type": "csv",
        "file_path": "./input.csv",
        "delimiter": ";"
    }
}

数据库版本:

{
    "base": {
        "output_path": "./processed_data",
        "chunk_size": 2000
    },
    "source": {
        "type": "db",
        "host": "localhost",
        "port": 5432,
        "database": "mydb",
        "username": "admin",
        "password": "123456",
        "query": "SELECT * FROM raw_data"
    }
}

配置解析逻辑

import json
from typing import Type

def parse_config(config_path: str) -> AppConfig:
    with open(config_path, "r") as f:
        config_dict = json.load(f)
    
    base_config = BaseConfig(**config_dict["base"])
    source_type = config_dict["source"]["type"]
    source_cls: Type[Union[CSVConfig, DBConfig]] = CSVConfig if source_type == "csv" else DBConfig
    source_config = source_cls(**config_dict["source"])
    
    return AppConfig(base=base_config, source=source_config)

二、策略模式封装数据获取逻辑

用Protocol定义统一的数据获取接口,分别实现CSV和数据库的数据源类,避免大量if判断,直接根据配置类型实例化对应策略。

接口与实现代码

from typing import Protocol
import pandas as pd
import sqlite3  # 以SQLite为例,其他数据库可替换连接逻辑

class DataSource(Protocol):
    def fetch_data(self, chunk_size: int) -> pd.DataFrame:
        """统一数据获取接口"""
        ...

class CSVDataSource:
    def __init__(self, config: CSVConfig):
        self.config = config
    
    def fetch_data(self, chunk_size: int):
        return pd.read_csv(
            self.config.file_path,
            delimiter=self.config.delimiter,
            encoding=self.config.encoding,
            chunksize=chunk_size
        )

class DBDataSource:
    def __init__(self, config: DBConfig):
        self.config = config
    
    def fetch_data(self, chunk_size: int):
        # 数据库分批查询逻辑,可根据数据库类型调整
        conn = sqlite3.connect(f"sqlite:///{self.config.host}:{self.config.port}/{self.config.database}")
        offset = 0
        while True:
            query = f"{self.config.query} LIMIT {chunk_size} OFFSET {offset}"
            df = pd.read_sql(query, conn)
            if df.empty:
                break
            yield df
            offset += chunk_size
        conn.close()

三、消除显式判断的优化方案

维护类型映射字典,将数据源类型字符串与配置类、策略类绑定,新增数据源时只需扩展映射,无需修改核心逻辑。

映射与主逻辑代码

# 类型映射:key为source.type值,value为(配置类, 策略类)
SOURCE_MAP = {
    "csv": (CSVConfig, CSVDataSource),
    "db": (DBConfig, DBDataSource)
}

# 优化配置解析函数
def parse_config(config_path: str) -> AppConfig:
    with open(config_path, "r") as f:
        config_dict = json.load(f)
    
    base_config = BaseConfig(**config_dict["base"])
    source_type = config_dict["source"]["type"]
    source_cls, _ = SOURCE_MAP[source_type]
    source_config = source_cls(**config_dict["source"])
    
    return AppConfig(base=base_config, source=source_config)

# 主逻辑
def main(config: AppConfig):
    source_type = config.source.type
    _, data_source_cls = SOURCE_MAP[source_type]
    data_source = data_source_cls(config.source)
    
    # 统一数据处理流程
    for chunk in data_source.fetch_data(config.base.chunk_size):
        print(f"Processing chunk with {len(chunk)} rows")
        chunk.to_csv(f"{config.base.output_path}/chunk_{offset}.csv", index=False)

if __name__ == "__main__":
    config = parse_config("config.json")
    main(config)

四、替代配置方案:Python文件作为配置

如果需要更强的类型校验和可读性,可直接用Python文件定义配置,无需额外解析:

示例config.py

from dataclasses import dataclass
from typing import Union

@dataclass
class BaseConfig:
    output_path: str
    chunk_size: int = 1000

@dataclass
class CSVConfig:
    type: str = "csv"
    file_path: str
    delimiter: str = ","
    encoding: str = "utf-8"

@dataclass
class DBConfig:
    type: str = "db"
    host: str
    port: int
    database: str
    username: str
    password: str
    query: str

@dataclass
class AppConfig:
    base: BaseConfig
    source: Union[CSVConfig, DBConfig]

# 具体配置实例
config = AppConfig(
    base=BaseConfig(
        output_path="./processed_data",
        chunk_size=2000
    ),
    source=CSVConfig(
        file_path="./input.csv",
        delimiter=";"
    )
)

主程序导入

from config import config

if __name__ == "__main__":
    main(config)

内容的提问来源于stack exchange,提问作者charlieshades

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 12:21:11