ITPub博客

首页 > 应用开发 > IT综合 > Python全局字典构建的全面指南与最佳实践

Python全局字典构建的全面指南与最佳实践

投稿 IT综合 作者:bhluo 时间:2025-12-18 17:16:09 0 删除 编辑

# Python全局字典构建的全面指南与最佳实践


## 引言:全局字典在Python应用中的角色


在Python应用程序开发中,全局字典作为一种共享数据存储机制,扮演着至关重要的角色。它们可以用于配置管理、状态跟踪、缓存实现、服务注册等多个场景。然而,不当的全局字典使用可能导致数据竞争、难以调试和维护问题。本文将深入探讨在Python中构建和管理全局字典的各种方法、设计模式以及最佳实践。


## 基础全局字典实现


### 模块级全局字典


最简单直接的全局字典实现是在模块级别定义字典变量。


```python

# config_store.py

"""模块级全局字典示例"""


# 基础全局字典

global_config = {

    "app_name": "MyApplication",

    "version": "1.0.0",

    "debug": False,

    "max_connections": 100,

    "timeout": 30.0

}


# 只读全局字典(约定俗成,实际并非真正只读)

_readonly_settings = {

    "api_version": "v2",

    "supported_formats": ["json", "xml"]

}


def get_setting(key, default=None):

    """安全获取配置项"""

    return global_config.get(key, default)


def update_settings(updates):

    """安全更新配置"""

    if not isinstance(updates, dict):

        raise TypeError("更新数据必须是字典")

    

    # 验证关键配置

    if "max_connections" in updates:

        if not isinstance(updates["max_connections"], int) or updates["max_connections"] <= 0:

            raise ValueError("max_connections必须是正整数")

    

    global_config.update(updates)

    return True


def get_readonly_setting(key):

    """获取只读配置"""

    return _readonly_settings.get(key)


# 使用示例

if __name__ == "__main__":

    # 访问配置

    print(f"应用名称: {get_setting('app_name')}")

    

    # 更新配置

    update_settings({"debug": True, "timeout": 45.0})

    print(f"调试模式: {get_setting('debug')}")

```


### 类包装的全局字典


使用类包装可以提供更好的封装和控制。


```python

# global_registry.py

"""类封装的全局字典"""


class GlobalRegistry:

    """全局注册表管理器"""

    

    _instance = None

    _registry = {}

    _locks = {}  # 用于线程安全的锁

    

    def __new__(cls):

        """单例模式实现"""

        if cls._instance is None:

            cls._instance = super().__new__(cls)

            cls._instance._initialize()

        return cls._instance

    

    def _initialize(self):

        """初始化注册表"""

        import threading

        self._lock = threading.RLock()

        

        # 初始化默认命名空间

        self._registry = {

            "config": {},

            "cache": {},

            "services": {},

            "state": {}

        }

    

    def set(self, namespace, key, value):

        """

        设置注册表项

        

        Args:

            namespace: 命名空间(如'config', 'cache')

            key: 键名

            value: 值

        """

        with self._lock:

            if namespace not in self._registry:

                self._registry[namespace] = {}

            self._registry[namespace][key] = value

    

    def get(self, namespace, key, default=None):

        """

        获取注册表项

        

        Args:

            namespace: 命名空间

            key: 键名

            default: 默认值

        """

        with self._lock:

            namespace_dict = self._registry.get(namespace)

            if namespace_dict is None:

                return default

            return namespace_dict.get(key, default)

    

    def delete(self, namespace, key):

        """删除注册表项"""

        with self._lock:

            if namespace in self._registry:

                self._registry[namespace].pop(key, None)

    

    def clear_namespace(self, namespace):

        """清空命名空间"""

        with self._lock:

            if namespace in self._registry:

                self._registry[namespace].clear()

    

    def get_namespace(self, namespace):

        """获取整个命名空间的拷贝"""

        with self._lock:

            if namespace in self._registry:

                return self._registry[namespace].copy()

            return {}

    

    def has_namespace(self, namespace):

        """检查命名空间是否存在"""

        return namespace in self._registry

    

    def list_namespaces(self):

        """列出所有命名空间"""

        return list(self._registry.keys())

    

    def dump(self):

        """导出整个注册表状态(用于调试)"""

        import json

        with self._lock:

            # 转换不可JSON序列化的对象

            serializable = {}

            for ns, data in self._registry.items():

                serializable[ns] = {}

                for k, v in data.items():

                    try:

                        json.dumps(v)

                        serializable[ns][k] = v

                    except:

                        serializable[ns][k] = str(v)

            

            return json.dumps(serializable, indent=2, ensure_ascii=False)


# 便捷访问函数

def get_registry():

    """获取全局注册表实例"""

    return GlobalRegistry()


def set_global(namespace, key, value):

    """便捷设置函数"""

    get_registry().set(namespace, key, value)


def get_global(namespace, key, default=None):

    """便捷获取函数"""

    return get_registry().get(namespace, key, default)


# 使用示例

if __name__ == "__main__":

    # 设置配置

    set_global("config", "database_url", "postgresql://user:pass@localhost/db")

    set_global("config", "max_workers", 4)

    

    # 设置缓存

    set_global("cache", "user_123", {"name": "Alice", "role": "admin"})

    

    # 获取值

    db_url = get_global("config", "database_url")

    print(f"数据库URL: {db_url}")

    

    # 导出状态

    registry = get_registry()

    print("注册表状态:")

    print(registry.dump())

```


## 线程安全的全局字典


### 使用锁机制的线程安全字典


```python

# thread_safe_dict.py

"""线程安全的全局字典实现"""


import threading

import time

from typing import Any, Dict, Optional, TypeVar, Generic

from contextlib import contextmanager

from collections.abc import MutableMapping


T = TypeVar('T')


class ThreadSafeDict(MutableMapping):

    """线程安全的字典实现"""

    

    def __init__(self, *args, **kwargs):

        self._data = dict(*args, **kwargs)

        self._lock = threading.RLock()

        self._condition = threading.Condition(self._lock)

    

    def __getitem__(self, key):

        with self._lock:

            return self._data[key]

    

    def __setitem__(self, key, value):

        with self._lock:

            self._data[key] = value

            # 通知等待的线程

            self._condition.notify_all()

    

    def __delitem__(self, key):

        with self._lock:

            del self._data[key]

    

    def __iter__(self):

        with self._lock:

            # 返回键的拷贝以避免迭代时修改

            return iter(list(self._data.keys()))

    

    def __len__(self):

        with self._lock:

            return len(self._data)

    

    def __repr__(self):

        with self._lock:

            return f"ThreadSafeDict({self._data})"

    

    def get(self, key, default=None):

        """线程安全的get方法"""

        with self._lock:

            return self._data.get(key, default)

    

    def setdefault(self, key, default=None):

        """线程安全的setdefault方法"""

        with self._lock:

            return self._data.setdefault(key, default)

    

    def pop(self, key, default=None):

        """线程安全的pop方法"""

        with self._lock:

            if key in self._data:

                return self._data.pop(key)

            return default

    

    def update(self, other=None, **kwargs):

        """线程安全的update方法"""

        with self._lock:

            if other is not None:

                if hasattr(other, "items"):

                    for k, v in other.items():

                        self._data[k] = v

                else:

                    for k, v in other:

                        self._data[k] = v

            

            for k, v in kwargs.items():

                self._data[k] = v

    

    def clear(self):

        """清空字典"""

        with self._lock:

            self._data.clear()

    

    def copy(self):

        """返回字典的深拷贝"""

        with self._lock:

            import copy

            return copy.deepcopy(self._data)

    

    def wait_for_key(self, key, timeout=None):

        """

        等待键出现

        

        Args:

            key: 等待的键

            timeout: 超时时间(秒)

        

        Returns:

            键的值或None(如果超时)

        """

        with self._condition:

            end_time = time.time() + timeout if timeout else None

            

            while key not in self._data:

                if timeout:

                    remaining = end_time - time.time()

                    if remaining <= 0:

                        return None

                    self._condition.wait(remaining)

                else:

                    self._condition.wait()

            

            return self._data[key]

    

    def atomic_update(self, key, update_func):

        """

        原子更新操作

        

        Args:

            key: 键名

            update_func: 更新函数,接受当前值,返回新值

        """

        with self._lock:

            current = self._data.get(key)

            new_value = update_func(current)

            self._data[key] = new_value

            return new_value

    

    @contextmanager

    def transaction(self):

        """

        事务上下文管理器

        

        用法:

        with dict_instance.transaction():

            dict_instance['key1'] = 'value1'

            dict_instance['key2'] = dict_instance['key1'] + '_suffix'

        """

        with self._lock:

            try:

                yield self

            except Exception:

                # 事务失败,可以选择回滚

                raise


# 全局线程安全字典管理器

class GlobalThreadSafeDict:

    """管理多个线程安全字典的全局管理器"""

    

    _instance = None

    _dicts = {}

    _creation_lock = threading.Lock()

    

    def __new__(cls):

        if cls._instance is None:

            with cls._creation_lock:

                if cls._instance is None:

                    cls._instance = super().__new__(cls)

                    cls._instance._initialize()

        return cls._instance

    

    def _initialize(self):

        self._dicts = ThreadSafeDict()

    

    def get_dict(self, name: str) -> ThreadSafeDict:

        """

        获取或创建命名的线程安全字典

        

        Args:

            name: 字典名称

        

        Returns:

            ThreadSafeDict实例

        """

        if name not in self._dicts:

            with self._dicts.transaction():

                if name not in self._dicts:

                    self._dicts[name] = ThreadSafeDict()

        

        return self._dicts[name]

    

    def remove_dict(self, name: str):

        """移除命名字典"""

        with self._dicts.transaction():

            if name in self._dicts:

                del self._dicts[name]

    

    def list_dicts(self):

        """列出所有字典名称"""

        return list(self._dicts.keys())


# 使用示例

def demo_thread_safe_dict():

    """演示线程安全字典的使用"""

www.ko.zizhitong.cn>www.qm.zizhitong.cn

    

    # 创建全局管理器

    manager = GlobalThreadSafeDict()

    

    # 获取配置字典

    config_dict = manager.get_dict("config")

    

    # 多个线程同时操作

    def worker_thread(thread_id):

        # 原子更新计数器

        def increment_counter(current):

            return (current or 0) + 1

        

        config_dict.atomic_update("request_count", increment_counter)

        

        # 设置线程特定的数据

        config_dict[f"thread_{thread_id}_data"] = {

            "started_at": time.time(),

            "thread_id": thread_id

        }

        

        # 等待共享资源

        if thread_id == 0:

            config_dict["shared_resource"] = "ready"

        else:

            # 其他线程等待资源就绪

            value = config_dict.wait_for_key("shared_resource", timeout=5)

            print(f"线程 {thread_id} 获取到资源: {value}")

    

    # 启动多个线程

    threads = []

    for i in range(5):

        t = threading.Thread(target=worker_thread, args=(i,))

        threads.append(t)

        t.start()

    

    # 等待所有线程完成

    for t in threads:

        t.join()

    

    # 输出结果

    print("最终配置字典:")

    print(config_dict.copy())

    print(f"总请求数: {config_dict.get('request_count', 0)}")


if __name__ == "__main__":

    demo_thread_safe_dict()

```


## 基于装饰器的全局字典访问


### 装饰器实现


```python

# global_dict_decorators.py

"""全局字典的装饰器实现"""


import functools

from typing import Any, Callable, Optional


class GlobalDictDecorators:

    """全局字典装饰器集合"""

    

    _storage = {}

    

    @classmethod

    def initialize(cls):

        """初始化存储"""

        cls._storage = {

            "cache": {},

            "config": {},

            "state": {},

            "metrics": {}

        }

    

    @classmethod

    def get_storage(cls, category="cache"):

        """获取存储字典"""

        if category not in cls._storage:

            cls._storage[category] = {}

        return cls._storage[category]

    

    @classmethod

    def cached(cls, category="cache", ttl=None):

        """

        缓存装饰器

        

        Args:

            category: 缓存类别

            ttl: 缓存存活时间(秒)

        """

        import time

        

        def decorator(func):

            @functools.wraps(func)

            def wrapper(*args, **kwargs):

                # 生成缓存键

                cache_key = f"{func.__module__}.{func.__name__}:{args}:{sorted(kwargs.items())}"

                cache_dict = cls.get_storage(category)

                

                # 检查缓存

                if cache_key in cache_dict:

                    cached_data = cache_dict[cache_key]

                    

                    # 检查TTL

                    if ttl is not None:

                        timestamp, value = cached_data

                        if time.time() - timestamp < ttl:

                            return value

                        else:

                            # 缓存过期,删除

                            del cache_dict[cache_key]

                    else:

                        return cached_data

                

                # 执行函数

                result = func(*args, **kwargs)

                

                # 缓存结果

                if ttl is not None:

                    cache_dict[cache_key] = (time.time(), result)

                else:

                    cache_dict[cache_key] = result

                

                return result

            

            return wrapper

        

        return decorator

    

    @classmethod

    def configurable(cls, config_key, default=None):

        """

        可配置的装饰器

        

        Args:

            config_key: 配置键名

            default: 默认值

        """

        def decorator(func):

            @functools.wraps(func)

            def wrapper(*args, **kwargs):

                # 获取配置

                config_dict = cls.get_storage("config")

                config_value = config_dict.get(config_key, default)

                

                # 将配置作为额外参数传递

                return func(*args, config=config_value, **kwargs)

            

            return wrapper

        

        return decorator

    

    @classmethod

    def stateful(cls, state_key):

        """

        有状态的装饰器

        

        Args:

            state_key: 状态键名

        """

        def decorator(func):

            @functools.wraps(func)

            def wrapper(*args, **kwargs):

                state_dict = cls.get_storage("state")

                

                # 获取或初始化状态

                if state_key not in state_dict:

                    state_dict[state_key] = {"call_count": 0}

                

                state = state_dict[state_key]

                state["call_count"] += 1

                state["last_called"] = time.time()

                

                try:

                    result = func(*args, **kwargs)

                    state["last_success"] = time.time()

                    return result

                except Exception as e:

                    state["last_error"] = str(e)

                    state["error_time"] = time.time()

                    raise

            

            return wrapper

        

        return decorator

    

    @classmethod

    def with_metrics(cls, metric_name):

        """

        带指标收集的装饰器

        

        Args:

            metric_name: 指标名称

        """

        import time

        

        def decorator(func):

            @functools.wraps(func)

            def wrapper(*args, **kwargs):

                start_time = time.time()

                metrics_dict = cls.get_storage("metrics")

                

                if metric_name not in metrics_dict:

                    metrics_dict[metric_name] = {

                        "count": 0,

                        "total_time": 0,

                        "errors": 0

                    }

                

                metrics = metrics_dict[metric_name]

                metrics["count"] += 1

                

                try:

                    result = func(*args, **kwargs)

                    execution_time = time.time() - start_time

                    metrics["total_time"] += execution_time

                    metrics["avg_time"] = metrics["total_time"] / metrics["count"]

                    return result

                except Exception:

                    metrics["errors"] += 1

                    raise

            

            return wrapper

        

        return decorator


# 使用示例

if __name__ == "__main__":

    GlobalDictDecorators.initialize()

    

    # 设置配置

    config_storage = GlobalDictDecorators.get_storage("config")

    config_storage["max_retries"] = 3

    config_storage["timeout"] = 10

    

    # 使用装饰器

    @GlobalDictDecorators.cached(category="api_cache", ttl=300)

    def fetch_user_data(user_id):

        print(f"从API获取用户数据: {user_id}")

        return {"id": user_id, "name": f"User_{user_id}", "active": True}

    

    @GlobalDictDecorators.configurable("max_retries", default=2)

    def retry_operation(operation, config=None):

        print(f"执行操作,最大重试次数: {config}")

        return f"操作完成,重试配置: {config}"

    

    @GlobalDictDecorators.stateful("data_processor")

    def process_data(data):

        print("处理数据...")

        return {"processed": True, "data": data}

    

    @GlobalDictDecorators.with_metrics("api_requests")

    def make_api_request(endpoint):

        print(f"请求API: {endpoint}")

        time.sleep(0.1)  # 模拟延迟

        return {"status": "success", "endpoint": endpoint}

    

    # 测试函数

    print("测试缓存装饰器:")

    print(fetch_user_data(1))

    print(fetch_user_data(1))  # 应该从缓存获取

    

    print("\n测试可配置装饰器:")

    print(retry_operation("重要操作"))

    

    print("\n测试有状态装饰器:")

    print(process_data({"test": "data"}))

    print(process_data({"test": "data2"}))

    

    print("\n测试指标装饰器:")

    print(make_api_request("/users"))

    print(make_api_request("/products"))

    

    # 查看状态和指标

    print("\n状态存储:")

    print(GlobalDictDecorators.get_storage("state"))

    

    print("\n指标存储:")

    print(GlobalDictDecorators.get_storage("metrics"))

```


## 应用场景实现


### 配置管理系统


```python

# configuration_manager.py

"""基于全局字典的配置管理系统"""


import json

import yaml

import os

from pathlib import Path

from typing import Dict, Any, Optional, Union

from threading import Lock

www.rp.zizhitong.cn>www.py.zizhitong.cn


class ConfigurationManager:

    """配置管理器"""

    

    _instance = None

    _config_store = {}

    _lock = Lock()

    _config_versions = {}

    

    # 配置验证规则

    VALIDATION_RULES = {

        "app.name": {"type": str, "required": True},

        "app.version": {"type": str, "required": True},

        "app.debug": {"type": bool, "default": False},

        "database.url": {"type": str, "required": True},

        "database.pool_size": {"type": int, "min": 1, "max": 100, "default": 10},

        "redis.host": {"type": str, "default": "localhost"},

        "redis.port": {"type": int, "min": 1, "max": 65535, "default": 6379},

        "logging.level": {"type": str, "choices": ["DEBUG", "INFO", "WARNING", "ERROR"], "default": "INFO"},

        "api.timeout": {"type": (int, float), "min": 0, "default": 30},

    }

    

    def __new__(cls):

        if cls._instance is None:

            with cls._lock:

                if cls._instance is None:

                    cls._instance = super().__new__(cls)

                    cls._instance._initialize()

        return cls._instance

    

    def _initialize(self):

        """初始化配置存储"""

        self._config_store = {}

        self._config_versions = {}

        self._load_defaults()

    

    def _load_defaults(self):

        """加载默认配置"""

        defaults = {

            "app": {

                "name": "MyApplication",

                "version": "1.0.0",

                "debug": False

            },

            "logging": {

                "level": "INFO",

                "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

            }

        }

        self._merge_config(defaults)

    

    def _merge_config(self, new_config: Dict, prefix: str = ""):

        """合并配置字典"""

        for key, value in new_config.items():

            full_key = f"{prefix}.{key}" if prefix else key

            

            if isinstance(value, dict):

                self._merge_config(value, full_key)

            else:

                self._config_store[full_key] = value

    

    def load_from_file(self, filepath: Union[str, Path]):

        """

        从文件加载配置

        

        Args:

            filepath: 配置文件路径

        

        Raises:

            FileNotFoundError: 文件不存在

            ValueError: 配置文件格式错误

        """

        filepath = Path(filepath)

        if not filepath.exists():

            raise FileNotFoundError(f"配置文件不存在: {filepath}")

        

        with open(filepath, 'r', encoding='utf-8') as f:

            if filepath.suffix.lower() in ['.yaml', '.yml']:

                config_data = yaml.safe_load(f)

            elif filepath.suffix.lower() == '.json':

                config_data = json.load(f)

            else:

                raise ValueError(f"不支持的配置文件格式: {filepath.suffix}")

        

        # 验证配置

        self._validate_config(config_data)

        

        # 保存版本

        version_key = f"config_version_{len(self._config_versions)}"

        self._config_versions[version_key] = self._config_store.copy()

        

        # 合并新配置

        self._merge_config(config_data)

    

    def load_from_env(self, prefix: str = "APP_"):

        """

        从环境变量加载配置

        

        Args:

            prefix: 环境变量前缀

        """

        env_config = {}

        

        for env_key, env_value in os.environ.items():

            if env_key.startswith(prefix):

                # 转换环境变量名:APP_DATABASE_URL -> database.url

                config_key = env_key[len(prefix):].lower().replace('_', '.')

                

                # 尝试转换类型

                try:

                    # 尝试转换为数字

                    if env_value.isdigit():

                        env_value = int(env_value)

                    elif env_value.replace('.', '', 1).isdigit():

                        env_value = float(env_value)

                    elif env_value.lower() in ['true', 'false']:

                        env_value = env_value.lower() == 'true'

                except (ValueError, AttributeError):

                    pass

                

                # 设置配置值

                self._set_dotted_key(config_key, env_value)

    

    def _set_dotted_key(self, dotted_key: str, value: Any):

        """设置点分隔的键"""

        parts = dotted_key.split('.')

        

        current = self._config_store

        for i, part in enumerate(parts[:-1]):

            if part not in current:

                current[part] = {}

            current = current[part]

        

        current[parts[-1]] = value

    

    def get(self, key: str, default: Any = None) -> Any:

        """

        获取配置值

        

        Args:

            key: 配置键(支持点分隔)

            default: 默认值

        

        Returns:

            配置值

        """

        try:

            return self._get_dotted_key(key)

        except KeyError:

            return default

    

    def _get_dotted_key(self, dotted_key: str) -> Any:

        """获取点分隔的键值"""

        parts = dotted_key.split('.')

www.kw.zizhitong.cn>www.dw.zizhitong.cn

        

        current = self._config_store

        for part in parts:

            if not isinstance(current, dict) or part not in current:

                raise KeyError(f"配置键不存在: {dotted_key}")

            current = current[part]

        

        return current

    

    def set(self, key: str, value: Any, validate: bool = True):

        """

        设置配置值

        

        Args:

            key: 配置键

            value: 配置值

            validate: 是否验证

        

        Raises:

            ValueError: 验证失败

        """

        if validate:

            self._validate_single_key(key, value)

        

        self._set_dotted_key(key, value)

    

    def _validate_config(self, config: Dict):

        """验证配置字典"""

        errors = []

        

        for rule_key, rule in self.VALIDATION_RULES.items():

            # 获取配置值

            try:

                value = self._get_dotted_key_from_dict(config, rule_key)

            except KeyError:

                if rule.get("required", False):

                    errors.append(f"缺少必需配置: {rule_key}")

                continue

            

            # 验证类型

            expected_type = rule.get("type")

            if expected_type and not isinstance(value, expected_type):

                errors.append(f"配置 {rule_key} 类型错误: 期望 {expected_type}, 实际 {type(value)}")

            

            # 验证范围

            if "min" in rule and value < rule["min"]:

                errors.append(f"配置 {rule_key} 值太小: 最小 {rule['min']}, 实际 {value}")

            

            if "max" in rule and value > rule["max"]:

                errors.append(f"配置 {rule_key} 值太大: 最大 {rule['max']}, 实际 {value}")

            

            # 验证选项

            if "choices" in rule and value not in rule["choices"]:

                errors.append(f"配置 {rule_key} 值无效: 允许 {rule['choices']}, 实际 {value}")

        

        if errors:

            raise ValueError(f"配置验证失败:\n" + "\n".join(errors))

    

    def _validate_single_key(self, key: str, value: Any):

        """验证单个配置项"""

        # 检查是否有验证规则

        for rule_key, rule in self.VALIDATION_RULES.items():

            if rule_key == key or rule_key.endswith(f".{key}"):

                expected_type = rule.get("type")

                if expected_type and not isinstance(value, expected_type):

                    raise ValueError(f"配置 {key} 类型错误: 期望 {expected_type}, 实际 {type(value)}")

                

                if "min" in rule and value < rule["min"]:

                    raise ValueError(f"配置 {key} 值太小: 最小 {rule['min']}, 实际 {value}")

                

                if "max" in rule and value > rule["max"]:

                    raise ValueError(f"配置 {key} 值太大: 最大 {rule['max']}, 实际 {value}")

                

                if "choices" in rule and value not in rule["choices"]:

                    raise ValueError(f"配置 {key} 值无效: 允许 {rule['choices']}, 实际 {value}")

    

    def _get_dotted_key_from_dict(self, data: Dict, dotted_key: str) -> Any:

        """从字典中获取点分隔的键值"""

        parts = dotted_key.split('.')

        

        current = data

        for part in parts:

            if not isinstance(current, dict) or part not in current:

                raise KeyError(f"键不存在: {dotted_key}")

            current = current[part]

        

        return current

    

    def to_dict(self) -> Dict:

        """导出配置为字典"""

        import copy

        return copy.deepcopy(self._config_store)

    

    def save_to_file(self, filepath: Union[str, Path], format: str = 'yaml'):

        """

        保存配置到文件

        

        Args:

            filepath: 文件路径

            format: 格式 ('yaml' 或 'json')

        """

        filepath = Path(filepath)

        

        with open(filepath, 'w', encoding='utf-8') as f:

            if format.lower() == 'yaml':

                yaml.dump(self.to_dict(), f, default_flow_style=False, allow_unicode=True)

            elif format.lower() == 'json':

                json.dump(self.to_dict(), f, indent=2, ensure_ascii=False)

            else:

                raise ValueError(f"不支持的格式: {format}")

    

    def watch_for_changes(self, filepath: Union[str, Path], interval: int = 60):

        """

        监视配置文件变化(示例)

        

        Args:

            filepath: 配置文件路径

            interval: 检查间隔(秒)

        """

        import threading

        import time

        

        def watcher():

            last_mtime = 0

            while True:

                try:

                    current_mtime = os.path.getmtime(filepath)

                    if current_mtime > last_mtime:

                        print(f"检测到配置文件变化,重新加载...")

                        self.load_from_file(filepath)

                        last_mtime = current_mtime

                except Exception as e:

                    print(f"监视配置文件时出错: {e}")

                

                time.sleep(interval)

        

        thread = threading.Thread(target=watcher, daemon=True)

        thread.start()

        return thread


# 使用示例

def demo_configuration_manager():

    """演示配置管理器的使用"""

    

    config = ConfigurationManager()

    

    # 从文件加载配置

    try:

        config.load_from_file("config.yaml")

    except FileNotFoundError:

        # 创建示例配置

        example_config = {

            "app": {

                "name": "示例应用",

                "version": "2.0.0"

            },

            "database": {

                "url": "postgresql://localhost/mydb",

                "pool_size": 20

            },

            "redis": {

                "host": "redis.local",

                "port": 6379

            }

        }

        

        import yaml

        with open("config.yaml", "w", encoding='utf-8') as f:

            yaml.dump(example_config, f)

        

        config.load_from_file("config.yaml")

    

    # 从环境变量加载

    os.environ["APP_API_TIMEOUT"] = "45"

    os.environ["APP_LOGGING_LEVEL"] = "DEBUG"

    config.load_from_env()

    

    # 获取配置

    print(f"应用名称: {config.get('app.name')}")

    print(f"数据库URL: {config.get('database.url')}")

    print(f"API超时: {config.get('api.timeout')}")

    print(f"日志级别: {config.get('logging.level')}")

    

    # 设置配置

    config.set("app.debug", True)

    print(f"调试模式: {config.get('app.debug')}")

    

    # 保存配置

    config.save_to_file("config_export.yaml")

    

    # 导出为字典

    config_dict = config.to_dict()

    print("\n完整配置:")

    print(json.dumps(config_dict, indent=2, ensure_ascii=False))


if __name__ == "__main__":

    demo_configuration_manager()

```


### 服务注册与发现


```python

# service_registry.py

"""基于全局字典的服务注册表"""


import inspect

import threading

from typing import Dict, Any, Callable, Optional, List

from dataclasses import dataclass, field

from datetime import datetime

from enum import Enum


class ServiceStatus(Enum):

    """服务状态"""

    REGISTERED = "registered"

    HEALTHY = "healthy"

    UNHEALTHY = "unhealthy"

    OFFLINE = "offline"


@dataclass

class ServiceInfo:

    """服务信息"""

    name: str

    instance: Any

    version: str = "1.0.0"

    status: ServiceStatus = ServiceStatus.REGISTERED

    metadata: Dict[str, Any] = field(default_factory=dict)

    registered_at: datetime = field(default_factory=datetime.now)

    last_health_check: Optional[datetime] = None

    

    def to_dict(self) -> Dict[str, Any]:

        """转换为字典"""

        return {

            "name": self.name,

            "version": self.version,

            "status": self.status.value,

            "metadata": self.metadata,

            "registered_at": self.registered_at.isoformat(),

            "last_health_check": self.last_health_check.isoformat() 

                if self.last_health_check else None

        }


class ServiceRegistry:

    """服务注册表"""

    

    _instance = None

    _services: Dict[str, ServiceInfo] = {}

    _service_locks: Dict[str, threading.RLock] = {}

    _registry_lock = threading.RLock()

    

    def __new__(cls):

        if cls._instance is None:

            with threading.Lock():

                if cls._instance is None:

                    cls._instance = super().__new__(cls)

        return cls._instance

    

    def register(self, name: str, instance: Any, 

                version: str = "1.0.0",

                metadata: Optional[Dict] = None) -> bool:

        """

        注册服务

        

        Args:

            name: 服务名称

            instance: 服务实例

            version: 服务版本

            metadata: 元数据

        

        Returns:

            是否注册成功

        """

        with self._registry_lock:

            if name in self._services:

                return False

            

            service_info = ServiceInfo(

                name=name,

                instance=instance,

                version=version,

                metadata=metadata or {},

                status=ServiceStatus.REGISTERED

            )

            

            self._services[name] = service_info

            self._service_locks[name] = threading.RLock()

            

            return True

    

    def unregister(self, name: str) -> bool:

        """

        注销服务

        

        Args:

            name: 服务名称

        

        Returns:

            是否注销成功

        """

        with self._registry_lock:

            if name not in self._services:

                return False

            

            del self._services[name]

            del self._service_locks[name]

            

            return True

    

    def get_service(self, name: str) -> Optional[Any]:

        """

        获取服务实例

        

        Args:

            name: 服务名称

        

        Returns:

            服务实例或None

        """

        with self._registry_lock:

            if name not in self._services:

                return None

            

            service_info = self._services[name]

            

            # 检查服务健康状态

            if service_info.status == ServiceStatus.UNHEALTHY:

                # 可以在这里实现故障转移或重试逻辑

                pass

            

            return service_info.instance

    

    def get_service_info(self, name: str) -> Optional[ServiceInfo]:

        """获取服务信息"""

        with self._registry_lock:

            return self._services.get(name)

    

    def list_services(self, status: Optional[ServiceStatus] = None) -> List[str]:

        """

        列出服务

        

        Args:

            status: 过滤状态

        

        Returns:

            服务名称列表

        """

        with self._registry_lock:

            if status is None:

                return list(self._services.keys())

            

            return [

                name for name, info in self._services.items()

                if info.status == status

            ]

    

    def update_status(self, name: str, status: ServiceStatus) -> bool:

        """

        更新服务状态

        

        Args:

            name: 服务名称

            status: 新状态

        

        Returns:

            是否更新成功

        """

        with self._registry_lock:

            if name not in self._services:

                return False

            

            service_info = self._services[name]

            service_info.status = status

            service_info.last_health_check = datetime.now()

            

            return True

    

    def health_check_all


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3105630/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-11-01

  • 博文量
    895
  • 访问量
    933968