python monkey_patch request.param

本文介绍了一种在Django框架中对GET请求参数进行校验的方法,通过monkey patch技术确保参数值符合预设范围,避免了因参数错误导致的程序异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用情景:

当request get的参数必须是某些参数时(如period,指定是day,week,month,year中的一个),创建py文件输入如下代码:

import django.core.handlers.wsgi

def monkey_patch_param(self, param_name, default_value, must_in=None):
    val = self.GET.get(param_name, default_value)
    if not must_in is None:
        if val not in must_in:
            val = default_value
    return val

django.core.handlers.wsgi.WSGIRequest.param = monkey_patch_param

将此文件import到你的views.py中即可。

使用:

period = request.param("period", "week", must_in=['day', 'week', 'month'])

如果用POST,将上面代码修改一下即可。

 

import eventlet eventlet.monkey_patch() from eventlet import wsgi import time from multiprocessing import Process import mediapipe as mp import numpy as np from flask import Flask, render_template from flask_socketio import SocketIO, Namespace import cv2 import base64 from threading import Lock import redis r = redis.Redis(host='localhost', port=6379) frame_lock = Lock() current_time = 0 last_frame_time = 0 frame_interval = 1 / 30 # 30FPS对应的间隔 # 优化后的初始化配置(平衡精度与性能) mp_pose = mp.solutions.pose pose = mp_pose.Pose( static_image_mode=False, # 视频流模式 model_complexity=1, # 改用中等复杂度模型(0-2范围) smooth_landmarks=True, enable_segmentation=False, # 关闭不必要的分割掩码 min_detection_confidence=0.7, # 提高检测阈值减少误判 min_tracking_confidence=0.3 # 降低跟踪阈值保持连续性 ) mp_drawing = mp.solutions.drawing_utils class Channel2(Namespace): def __init__(self, namespace): super().__init__(namespace) self.pubsub = r.pubsub() self.pubsub.subscribe('frame_channel') self.running = True self.thread = None def calculate_angle(self, a, b, c): #"""计算三个关节点构成的夹角(单位:度)""" a = np.array(a) # 起点 b = np.array(b) # 顶点 c = np.array(c) # 终点 ba = a - b bc = c - b cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc)) angle = np.degrees(np.arccos(cosine_angle)) return angle def is_landmark_visible(self, landmark, threshold=0.5): return hasattr(landmark, 'visibility') and landmark.visibility > threshold def process_image(self, imgRGB, img): global last_frame_time, current_time if imgRGB is not None and img is not None: results = pose.process(imgRGB) if results.pose_landmarks: mp_drawing.draw_landmarks(img, results.pose_landmarks, mp_pose.POSE_CONNECTIONS) encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 80] ret, buffer = cv2.imencode('.jpg', img, encode_param) b64_frame = base64.b64encode(buffer).decode('utf-8') last_frame_time = current_time return b64_frame else: encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 80] ret, buffer = cv2.imencode('.jpg', img, encode_param) b64_frame = base64.b64encode(buffer).decode('utf-8') last_frame_time = current_time return b64_frame def getImgs(self, data): # 处理原始帧 img_np = np.frombuffer(data, dtype=np.uint8) img = cv2.imdecode(img_np, cv2.IMREAD_COLOR) imgRGB = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) outputs = self.process_image(imgRGB, img) self.emit('server_callback', { 'type': 'processed', 'frame': f'data:image/jpeg;base64,{outputs}' }, namespace='/processor', callback=lambda status: print(f"Client received: {status}")) def on_connect(self, auth): print('通道2连接建立') print(auth, '=====') def listener(): while self.running: message = self.pubsub.get_message() if message and message['type'] == 'message': self.getImgs(message['data']) eventlet.sleep(0.001) listener() def on_disconnect(self): print('通道2连接关闭') self.running = False if self.thread: self.thread.kill() def create_app(port): app = Flask(__name__) socketio = SocketIO(app, cors_allowed_origins='*', async_mode='eventlet', ping_interval=5000) @app.route('/') def index(): return render_template('rtc2.html') return app, socketio class Channel1(Namespace): def on_connect(self): print("通道1连接建立") def passImg(self, data): global last_frame_time, frame_interval, current_time current_time = time.time() # 帧率控制 if current_time - last_frame_time < frame_interval: print('/////////////') return else: with frame_lock: r.publish('frame_channel', data) last_frame_time = current_time def on_frame_exchange(self, data): self.passImg(data) def on_disconnect(self): print('通道1连接关闭') def run_primary(): app, socketio = create_app(5001) socketio.on_namespace(Channel1('/upload')) socketio.run(app, port=5001, debug=True) def run_secondary(): app, socketio = create_app(5002) socketio.on_namespace(Channel2('/processor')) socketio.run(app, port=5002, debug=True) if __name__ == '__main__': Process(target=run_primary).start() Process(target=run_secondary).start()
07-03
================================================ AI系统正在启动 [周一 2025/08/11 22:52:48.99] ================================================ [1/3] 启动模型API服务... 2025-08-11 22:52:49,235 - APIServer - INFO - 开始初始化模型... 2025-08-11 22:52:52,366 - APIServer - CRITICAL - 模型初始化异常: cannot import name 'cached_download' from 'huggingface_hub' (E:\Python310\lib\site-packages\huggingface_hub\__init__.py) ================================================== Starting DeepSeek-7B Model API Server Start Time: 2025-08-11T14:52:52.367935Z Model Status: Not Loaded ================================================== API Endpoints: - Generate: POST http://127.0.0.1:6000/generate - Status: GET http://127.0.0.1:6000/status - Health: GET http://127.0.0.1:6000/health ================================================== * Serving Flask app 'api_server' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on http://127.0.0.1:6000 Press CTRL+C to quit [2/3] 启动AI核心服务... Traceback (most recent call last): File "E:\AI_System\agent\agent_core.py", line 24, in <module> from agent.cognitive_architecture import CognitiveArchitecture File "E:\AI_System\agent\__init__.py", line 5, in <module> from .autonomous_agent import AutonomousAgent # 修改此处 File "E:\AI_System\agent\autonomous_agent.py", line 19, in <module> from core.config import system_config ImportError: cannot import name 'system_config' from 'core.config' (E:\AI_System\core\config.py) [3/3] 启动用户界面... 系统启动完成!自动打开监控页面... ✅ Eventlet monkey patch applied at startup 2025-08-11 22:52:57 [INFO] WebServer: ================================================== 2025-08-11 22:52:57 [INFO] WebServer: 🚀 开始初始化AI系统 2025-08-11 22:52:57 [INFO] WebServer: ================================================== 2025-08-11 22:52:57 [INFO] WebServer: 项目根目录: E:\AI_System 2025-08-11 22:52:57 [INFO] WebServer: 添加路径: E:\AI_System\agent 2025-08-11 22:52:57 [INFO] WebServer: 添加路径: E:\AI_System\core 2025-08-11 22:52:57 [INFO] WebServer: 添加路径: E:\AI_System\utils 2025-08-11 22:52:57 [INFO] WebServer: 添加路径: E:\AI_System\config 2025-08-11 22:52:57 [INFO] WebServer: 添加路径: E:\AI_System\cognitive_arch 2025-08-11 22:52:57 [INFO] WebServer: 添加路径: E:\AI_System\environment 2025-08-11 22:52:57 [INFO] WebServer: ✅ 模拟AI核心初始化 2025-08-11 22:52:57 [INFO] WebServer: ✅ 模拟硬件管理器初始化 2025-08-11 22:52:57 [INFO] WebServer: ✅ 模拟生活调度器初始化 2025-08-11 22:52:57 [INFO] WebServer: ✅ 模拟AI智能体初始化 2025-08-11 22:52:57 [INFO] WebServer: 环境管理器已启动 2025-08-11 22:52:57 [INFO] WebServer: ✅ 环境管理器初始化成功 2025-08-11 22:52:57 [INFO] WebServer: ✅ 模拟进化监视器启动 2025-08-11 22:52:57 [INFO] WebServer: ✅ 所有系统组件初始化完成 2025-08-11 22:52:57 [INFO] WebServer: ✅ 使用eventlet异步模式 2025-08-11 22:52:57 [INFO] WebServer: 🚀 开发服务器启动: http://0.0.0.0:5000 (17256) wsgi starting up on http://0.0.0.0:5000 ================================================ 运行中进程: python.exe 16140 Console 1 210,852 K python.exe 17256 Console 1 50,544 K ================================================ 按任意键退出此窗口(服务将继续在后台运行)... (17256) accepted ('127.0.0.1', 50016) (17256) accepted ('127.0.0.1', 50032) 127.0.0.1 - - [11/Aug/2025 22:53:21] "GET / HTTP/1.1" 200 3308 0.001000 127.0.0.1 - - [11/Aug/2025 22:53:21] "GET /favicon.ico HTTP/1.1" 404 212 0.000000 127.0.0.1 - - [11/Aug/2025 22:53:29] "GET /life/dashboard HTTP/1.1" 200 32013 0.003999 Traceback (most recent call last): File "E:\Python310\lib\site-packages\flask\app.py", line 2193, in wsgi_app response = self.handle_exception(e) File "E:\Python310\lib\site-packages\flask\app.py", line 2190, in wsgi_app response = self.full_dispatch_request() File "E:\Python310\lib\site-packages\flask\app.py", line 1486, in full_dispatch_request rv = self.handle_user_exception(e) File "E:\Python310\lib\site-packages\flask\app.py", line 1484, in full_dispatch_request rv = self.dispatch_request() File "E:\Python310\lib\site-packages\flask\app.py", line 1469, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) File "E:\AI_System\web_ui\server.py", line 467, in status "hardware_status": components['hardware_manager'].get_status() if components[ TypeError: SystemInitializer.initialize_hardware_manager.<locals>.<lambda>() takes 0 positional arguments but 1 was given 127.0.0.1 - - [11/Aug/2025 22:53:42] "GET /status HTTP/1.1" 500 12795 0.012914 127.0.0.1 - - [11/Aug/2025 22:53:42] "GET /status?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 304 183 0.016000 127.0.0.1 - - [11/Aug/2025 22:53:42] "GET /status?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 304 184 0.000000 127.0.0.1 - - [11/Aug/2025 22:53:42] "GET /status?__debugger__=yes&cmd=resource&f=console.png&s=cy8AirLRNcqty2WTg3dx HTTP/1.1" 200 729 0.001000 127.0.0.1 - - [11/Aug/2025 22:53:54] "GET /health HTTP/1.1" 200 203 0.001001 127.0.0.1 - - [11/Aug/2025 22:53:57] "GET /chat HTTP/1.1" 200 2844 0.009460 127.0.0.1 - - [11/Aug/2025 22:53:59] "GET /socket.io/?EIO=4&transport=polling&t=PYPdxlY HTTP/1.1" 200 300 0.000000 2025-08-11 22:53:59 [INFO] WebServer: 客户端已连接 127.0.0.1 - - [11/Aug/2025 22:53:59] "POST /socket.io/?EIO=4&transport=polling&t=PYPdxla&sid=y_bOfyPWaorXA7sEAAAA HTTP/1.1" 200 219 0.001000 (17256) accepted ('127.0.0.1', 50075) 127.0.0.1 - - [11/Aug/2025 22:53:59] "GET /socket.io/?EIO=4&transport=polling&t=PYPdxlb&sid=y_bOfyPWaorXA7sEAAAA HTTP/1.1" 200 252 0.000000 127.0.0.1 - - [11/Aug/2025 22:53:59] "GET /socket.io/?EIO=4&transport=polling&t=PYPdxlc&sid=y_bOfyPWaorXA7sEAAAA HTTP/1.1" 200 181 0.000000 127.0.0.1 - - [11/Aug/2025 22:53:59] "GET /socket.io/?EIO=4&transport=polling&t=PYPdxle&sid=y_bOfyPWaorXA7sEAAAA HTTP/1.1" 200 181 0.000000 2025-08-11 22:54:01 [INFO] WebServer: 收到来自 user_1754924041725 的消息: hi 2025-08-11 22:54:08 [INFO] WebServer: 收到来自 user_1754924048779 的消息: 能听见吗 2025-08-11 22:54:13 [INFO] WebServer: 客户端已断开连接 127.0.0.1 - - [11/Aug/2025 22:54:13] "GET /socket.io/?EIO=4&transport=websocket&sid=y_bOfyPWaorXA7sEAAAA HTTP/1.1" 200 0 14.650252 127.0.0.1 - - [11/Aug/2025 22:54:14] "GET /environment HTTP/1.1" 200 47268 0.014014 #E:\AI_System\core\config.py # import os import json import logging import configparser from pathlib import Path from typing import Dict, Any, Optional, Union from dotenv import load_dotenv class CoreConfig: """ 核心配置管理类 - 提供统一的配置管理接口 支持多来源配置加载:环境变量 > 配置文件 > 默认值 """ def __init__(self, config_path: Optional[Union[str, Path]] = None, env_prefix: str = "APP_", default_config: Optional[Dict[str, Any]] = None): """ 初始化配置管理器 :param config_path: 配置文件路径(支持.json, .ini, .env) :param env_prefix: 环境变量前缀 :param default_config: 默认配置字典 """ self.logger = logging.getLogger('CoreConfig') self._setup_logger() self.env_prefix = env_prefix self.config_path = Path(config_path) if config_path else None self.config_data = default_config or {} self.config_modified = False self.log(f"📋 初始化配置管理器 | 环境前缀: {env_prefix}") # 加载配置 self.load_configuration() def _setup_logger(self): """配置日志记录器""" if not self.logger.handlers: handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) self.logger.addHandler(handler) self.logger.setLevel(logging.INFO) self.logger.propagate = False def log(self, message: str, level: str = "info"): """记录日志""" log_levels = { "debug": self.logger.debug, "info": self.logger.info, "warning": self.logger.warning, "error": self.logger.error } log_func = log_levels.get(level.lower(), self.logger.info) log_func(message) def load_configuration(self): """加载所有配置源""" # 1. 加载环境变量 self._load_environment_vars() # 2. 加载配置文件(如果存在) if self.config_path and self.config_path.exists(): self._load_config_file() elif self.config_path: self.log(f"⚠️ 配置文件不存在: {self.config_path}", "warning") self.log(f"✅ 配置加载完成 | 条目数: {len(self.config_data)}") def _load_environment_vars(self): """加载环境变量""" self.log("🔍 加载环境变量...") load_dotenv() # 加载.env文件(如果存在) # 获取所有以指定前缀开头的环境变量 for key, value in os.environ.items(): if key.startswith(self.env_prefix): config_key = key[len(self.env_prefix):].lower() self.config_data[config_key] = self._parse_value(value) self.log(f" - 加载环境变量: {config_key} = {self._mask_secret(config_key, value)}") def _load_config_file(self): """根据文件扩展名加载配置文件""" suffix = self.config_path.suffix.lower() self.log(f"📄 加载配置文件: {self.config_path} (类型: {suffix[1:]})") try: if suffix == '.json': self._load_json_config() elif suffix in ('.ini', '.cfg'): self._load_ini_config() elif suffix == '.env': self._load_dotenv_config() else: self.log(f"❌ 不支持的配置文件类型: {suffix}", "error") except Exception as e: self.log(f"❌ 配置文件加载失败: {str(e)}", "error") def _load_json_config(self): """加载JSON配置文件""" with open(self.config_path, 'r', encoding='utf-8') as f: json_data = json.load(f) self._merge_config(json_data) def _load_ini_config(self): """加载INI配置文件""" parser = configparser.ConfigParser() parser.read(self.config_path) config_dict = {} for section in parser.sections(): section_dict = {} for key, value in parser.items(section): section_dict[key] = self._parse_value(value) config_dict[section] = section_dict self._merge_config(config_dict) def _load_dotenv_config(self): """加载.env配置文件""" # 已由load_dotenv()处理,这里只需记录 self.log(" - .env文件已加载") def _merge_config(self, new_config: Dict[str, Any]): """合并新配置到现有配置""" for key, value in new_config.items(): # 处理嵌套配置 if isinstance(value, dict) and key in self.config_data and isinstance(self.config_data[key], dict): self.config_data[key].update(value) else: self.config_data[key] = value self.log(f" - 加载配置项: {key} = {self._mask_secret(key, value)}") def _parse_value(self, value: str) -> Any: """智能解析字符串值为合适的Python类型""" # 尝试解析为布尔值 if value.lower() in ('true', 'yes', 'on'): return True if value.lower() in ('false', 'no', 'off'): return False # 尝试解析为数字 try: return int(value) except ValueError: try: return float(value) except ValueError: pass # 尝试解析为列表 if ',' in value: return [self._parse_value(item.strip()) for item in value.split(',')] # 返回原始字符串 return value def _mask_secret(self, key: str, value: Any) -> str: """对敏感信息进行掩码处理""" if 'secret' in key or 'password' in key or 'key' in key: return '******' if value else '空' if isinstance(value, list): return f"[列表, 长度: {len(value)}]" if isinstance(value, dict): return f"{{字典, 键数: {len(value)}}}" return str(value) def get(self, key: str, default: Any = None) -> Any: """ 获取配置值,支持点分路径 (如: 'database.host') :param key: 配置键名 :param default: 默认值(如果键不存在) :return: 配置值 """ keys = key.split('.') current = self.config_data for k in keys: if isinstance(current, dict) and k in current: current = current[k] else: return default return current def set(self, key: str, value: Any, persist: bool = False): """ 设置配置值 :param key: 配置键名 :param value: 配置值 :param persist: 是否持久化到配置文件 """ keys = key.split('.') current = self.config_data # 遍历创建嵌套字典 for i, k in enumerate(keys[:-1]): if k not in current or not isinstance(current[k], dict): current[k] = {} current = current[k] # 设置最终值 last_key = keys[-1] current[last_key] = value self.config_modified = True self.log(f"⚙️ 设置配置: {key} = {self._mask_secret(last_key, value)}") # 持久化到文件 if persist and self.config_path: self.save_config() def save_config(self, path: Optional[Union[str, Path]] = None): """ 保存配置到文件 :param path: 可选的自定义保存路径 """ save_path = Path(path) if path else self.config_path if not save_path: self.log("❌ 保存失败: 未指定配置文件路径", "error") return False suffix = save_path.suffix.lower() try: if suffix == '.json': with open(save_path, 'w', encoding='utf-8') as f: json.dump(self.config_data, f, indent=2, ensure_ascii=False) elif suffix in ('.ini', '.cfg'): self._save_ini_config(save_path) else: self.log(f"❌ 不支持的文件格式: {suffix}", "error") return False self.log(f"💾 配置已保存到: {save_path}") self.config_modified = False return True except Exception as e: self.log(f"❌ 配置保存失败: {str(e)}", "error") return False def _save_ini_config(self, path: Path): """保存为INI格式配置文件""" parser = configparser.ConfigParser() # 递归处理嵌套字典 def add_section(data, section_name=None): if section_name: parser.add_section(section_name) for key, value in data.items(): if isinstance(value, dict): add_section(value, f"{section_name}.{key}" if section_name else key) else: if not section_name: parser.set('DEFAULT', key, str(value)) else: parser.set(section_name, key, str(value)) add_section(self.config_data) with open(path, 'w', encoding='utf-8') as f: parser.write(f) def reload(self): """重新加载所有配置源""" self.log("🔄 重新加载配置...") self.config_data = {} self.load_configuration() def to_dict(self) -> Dict[str, Any]: """返回当前配置的完整字典""" return self.config_data.copy() def __getitem__(self, key: str) -> Any: """支持字典式访问""" return self.get(key) def __setitem__(self, key: str, value: Any): """支持字典式设置""" self.set(key, value) def __contains__(self, key: str) -> bool: """检查配置项是否存在""" return self.get(key) is not None # 测试代码 if __name__ == "__main__": logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) print("=" * 50) print("核心配置管理器测试") print("=" * 50) # 创建临时配置文件 config_json = """ { "database": { "host": "localhost", "port": 5432, "username": "admin", "password": "db_secret" }, "logging": { "level": "INFO", "path": "/var/log/app.log" }, "features": ["auth", "caching", "analytics"] } """ with open("test_config.json", "w") as f: f.write(config_json) # 设置环境变量 os.environ["APP_API_KEY"] = "env_secret_key" os.environ["APP_DATABASE_PORT"] = "6432" # 覆盖配置文件中的端口 # 创建配置管理器实例 config = CoreConfig( config_path="test_config.json", env_prefix="APP_", default_config={ "app_name": "MyApp", "version": "1.0.0" } ) # 测试配置获取 print("\n测试配置获取:") print(f"数据库主机: {config.get('database.host')}") print(f"数据库端口: {config.get('database.port')} (应被环境变量覆盖)") print(f"API密钥: {config.get('api_key')} (来自环境变量)") print(f"应用名称: {config.get('app_name')} (来自默认配置)") print(f"日志级别: {config.get('logging.level')}") print(f"功能列表: {config.get('features')}") # 测试配置设置 print("\n测试配置设置:") config.set("new_feature.enabled", True) config.set("database.password", "new_secret", persist=True) print(f"新功能状态: {config.get('new_feature.enabled')}") # 测试配置保存 print("\n测试配置保存:") config.save_config("test_config_saved.json") # 测试配置包含检查 print("\n测试配置包含检查:") print(f"数据库用户名存在: {'database.username' in config}") print(f"不存在的键: {'nonexistent.key' in config}") # 测试配置转字典 print("\n完整配置字典:") print(json.dumps(config.to_dict(), indent=2, ensure_ascii=False))
最新发布
08-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值