redis.exceptions.DataError: Invalid input of type: ‘dict‘. Convert to a byte, string or number first

214 篇文章 ¥49.90 ¥99.00
本文介绍了在使用Python与Redis交互时遇到的DataError问题,当尝试写入字典类型数据时,报错'Invalid input of type: 'dict'. Convert to a byte, string or number first.'。解决方案是检查Redis版本,将版本降低到2.10.6以解决问题。" 126801768,12582781,Go语言面试题大全,"['Go', '并发', '内存管理', '面试准备', '并发编程']

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

目录

一、项目场景

二、问题描述

三、解决方案


一、项目场景

利用python往redis写数据,报错。


二、问题描述

redis.exceptions.DataError: Invalid input of type: 'dict'. Convert to a byte, string or number first.


三、解决方案

查看当前redis版本

pip freeze

 可以看到,当前版本是4.3.4。

对redis进行降级处理,

无法查找到HTML模板,我的程序如下from flask import Flask, render_template, request, jsonify, redirect, url_for from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user from werkzeug.security import generate_password_hash, check_password_hash import requests import json import os import uuid import redis import time from datetime import datetime, UTC from functools import wraps from dotenv import load_dotenv # 加载环境变量 load_dotenv() base_dir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__, template_folder=os.path.join(base_dir, 'templates'), static_folder=os.path.join(base_dir, 'static')) print(f"当前文件位置: {os.path.abspath(__file__)}") print(f"项目根目录: {base_dir}") print(f"模板路径: {app.template_folder}") print(f"模板目录内容: {os.listdir(app.template_folder)}") app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'supersecretkey') app.config[ 'SQLALCHEMY_DATABASE_URI'] = f"mysql+mysqlconnector://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@{os.getenv('DB_HOST')}/{os.getenv('DB_NAME')}" app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['COZE_API_KEY'] = os.getenv('COZE_API_KEY') app.config['COZE_BOT_ID'] = os.getenv('COZE_BOT_ID') app.config['COZE_API_URL'] = "https://api.coze.cn/v3/chat" app.config['REDIS_URL'] = os.getenv('REDIS_URL', 'redis://localhost:6379/0') app.config['TOKEN_PRICE'] = 0.01 # 每个token的价格(美元) # 初始化扩展 db = SQLAlchemy(app) login_manager = LoginManager(app) login_manager.login_view = 'login' # 初始化Redis redis_client = redis.Redis.from_url(app.config['REDIS_URL']) # 数据库模型 class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(50), unique=True, nullable=False) password = db.Column(db.String(255), nullable=False) email = db.Column(db.String(100), unique=True, nullable=False) is_admin = db.Column(db.Boolean, default=False) token_balance = db.Column(db.Integer, default=0) created_at = db.Column(db.DateTime, default=lambda: datetime.now(UTC)) api_keys = db.relationship('APIKey', backref='user', lazy=True) recharges = db.relationship('Recharge', backref='user', foreign_keys='Recharge.user_id', lazy=True) messages = db.relationship('MessageCache', backref='user', lazy=True) class APIKey(db.Model): __tablename__ = 'api_keys' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) api_key = db.Column(db.String(255), unique=True, nullable=False) is_active = db.Column(db.Boolean, default=True) created_at = db.Column(db.DateTime, default=lambda: datetime.now(UTC)) class Recharge(db.Model): __tablename__ = 'recharges' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) admin_id = db.Column(db.Integer, db.ForeignKey('users.id')) amount = db.Column(db.Integer, nullable=False) status = db.Column(db.String(20), default='pending') created_at = db.Column(db.DateTime, default=lambda: datetime.now(UTC)) processed_at = db.Column(db.DateTime) # 明确指定关系 admin = db.relationship('User', foreign_keys=[admin_id]) class MessageCache(db.Model): __tablename__ = 'message_cache' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) request = db.Column(db.Text, nullable=False) response = db.Column(db.Text, nullable=False) tokens_used = db.Column(db.Integer, nullable=False) created_at = db.Column(db.DateTime, default=lambda: datetime.now(UTC)) # Flask-Login 用户加载器 @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) # 认证装饰器 def admin_required(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_admin: return redirect(url_for('dashboard')) return f(*args, **kwargs) return decorated_function # 工具函数 def generate_api_key(): return str(uuid.uuid4()).replace('-', '') def format_to_openai(coze_response): """将Coze API响应转换为OpenAI格式""" choices = [] if 'messages' in coze_response: for msg in coze_response['messages']: if msg['role'] == 'assistant': choices.append({ "index": 0, "message": { "role": "assistant", "content": msg.get('content', '') }, "finish_reason": "stop" }) usage = coze_response.get('usage', {}) return { "id": f"chatcmpl-{int(time.time())}", "object": "chat.completion", "created": int(time.time()), "model": "coze-bot", "choices": choices, "usage": { "prompt_tokens": usage.get('prompt_tokens', 0), "completion_tokens": usage.get('completion_tokens', 0), "total_tokens": usage.get('total_tokens', 0) } } def deduct_tokens(user_id, amount): """扣除用户token""" user = User.query.get(user_id) if not user or user.token_balance < amount: return False user.token_balance -= amount db.session.commit() return True def add_tokens(user_id, amount): """增加用户token""" user = User.query.get(user_id) if not user: return False user.token_balance += amount db.session.commit() return True # 路由定义 @app.route('/') def index(): template_path = os.path.join(app.template_folder, 'index.html') if not os.path.exists(template_path): return f"模板文件不存在!路径: {template_path}", 500 try: return render_template('index.html') except Exception as e: return f"渲染错误: {str(e)}", 500 @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] user = User.query.filter_by(username=username).first() if user and check_password_hash(user.password, password): login_user(user) return redirect(url_for('dashboard')) return render_template('login.html', error='Invalid username or password') return render_template('login.html') @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form['username'] email = request.form['email'] password = generate_password_hash(request.form['password']) admin_code = request.form.get('admin_code', '') # 检查用户名和邮箱是否已存在 if User.query.filter_by(username=username).first(): return render_template('register.html', error='Username already exists') if User.query.filter_by(email=email).first(): return render_template('register.html', error='Email already exists') is_admin = admin_code == '789456123' new_user = User( username=username, email=email, password=password, is_admin=is_admin ) db.session.add(new_user) db.session.commit() login_user(new_user) return redirect(url_for('dashboard')) return render_template('register.html') @app.route('/logout') @login_required def logout(): logout_user() return redirect(url_for('index')) @app.route('/dashboard') @login_required def dashboard(): return render_template('dashboard.html', user=current_user) @app.route('/admin/dashboard') @login_required @admin_required def admin_dashboard(): users = User.query.all() pending_recharges = Recharge.query.filter_by(status='pending').all() return render_template('admin_dashboard.html', users=users, recharges=pending_recharges) @app.route('/generate-api-key', methods=['POST']) @login_required def generate_api_key_route(): new_key = APIKey( user_id=current_user.id, api_key=generate_api_key() ) db.session.add(new_key) db.session.commit() return redirect(url_for('api_keys')) @app.route('/api-keys') @login_required def api_keys(): return render_template('api_keys.html', api_keys=current_user.api_keys) @app.route('/toggle-api-key/<int:key_id>', methods=['POST']) @login_required def toggle_api_key(key_id): api_key = APIKey.query.get_or_404(key_id) if api_key.user_id != current_user.id and not current_user.is_admin: return jsonify({"error": "Unauthorized"}), 403 api_key.is_active = not api_key.is_active db.session.commit() return redirect(url_for('api_keys')) @app.route('/recharge', methods=['POST']) @login_required def recharge(): try: amount = int(request.form['amount']) except ValueError: return render_template('dashboard.html', user=current_user, error='Invalid amount') if amount <= 0: return render_template('dashboard.html', user=current_user, error='Amount must be positive') new_recharge = Recharge( user_id=current_user.id, amount=amount ) db.session.add(new_recharge) db.session.commit() return render_template('dashboard.html', user=current_user, success='Recharge request submitted') @app.route('/admin/approve-recharge/<int:recharge_id>', methods=['POST']) @login_required @admin_required def approve_recharge(recharge_id): recharge = Recharge.query.get_or_404(recharge_id) if recharge.status != 'pending': return jsonify({"error": "Recharge already processed"}), 400 recharge.status = 'approved' recharge.processed_at = lambda: datetime.now(UTC) recharge.admin_id = current_user.id add_tokens(recharge.user_id, recharge.amount) db.session.commit() return redirect(url_for('admin_dashboard')) @app.route('/admin/reject-recharge/<int:recharge_id>', methods=['POST']) @login_required @admin_required def reject_recharge(recharge_id): recharge = Recharge.query.get_or_404(recharge_id) if recharge.status != 'pending': return jsonify({"error": "Recharge already processed"}), 400 recharge.status = 'rejected' recharge.processed_at = lambda: datetime.now(UTC) recharge.admin_id = current_user.id db.session.commit() return redirect(url_for('admin_dashboard')) @app.route('/admin/update-tokens/<int:user_id>', methods=['POST']) @login_required @admin_required def update_tokens(user_id): user = User.query.get_or_404(user_id) try: amount = int(request.form['amount']) except ValueError: return jsonify({"error": "Invalid amount"}), 400 user.token_balance = amount db.session.commit() return redirect(url_for('admin_dashboard')) @app.route('/admin/toggle-user/<int:user_id>', methods=['POST']) @login_required @admin_required def toggle_user(user_id): user = User.query.get_or_404(user_id) # 切换所有API密钥状态 for api_key in user.api_keys: api_key.is_active = not api_key.is_active db.session.commit() return redirect(url_for('admin_dashboard')) # API端点 @app.route('/v1/chat/completions', methods=['POST']) def chat_completion(): # 验证API密钥 auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return jsonify({"error": "Missing API key"}), 401 api_key = auth_header[7:] # 移除"Bearer " api_key_obj = APIKey.query.filter_by(api_key=api_key).first() if not api_key_obj or not api_key_obj.is_active: return jsonify({"error": "Invalid API key"}), 401 user = api_key_obj.user # 检查token余额 if user.token_balance <= 0: return jsonify({"error": "Insufficient token balance"}), 403 # 尝试从Redis缓存获取响应 cache_key = f"request:{api_key}:{hash(str(request.json))}" cached_response = redis_client.get(cache_key) if cached_response: return jsonify(json.loads(cached_response)) # 处理图片和文本 messages = request.json.get('messages', []) coze_messages = [] for msg in messages: if 'content' in msg: # 简单判断是否为图片(实际应用中可能需要更复杂的逻辑) content_type = 'image' if isinstance(msg['content'], dict) or msg['content'].startswith( 'data:image') else 'text' coze_messages.append({ "role": msg['role'], "content": msg['content'], "content_type": content_type }) # 构建Coze API请求 coze_data = { "bot_id": app.config['COZE_BOT_ID'], "user_id": str(user.id), "stream": False, "auto_save_history": True, "additional_messages": coze_messages } headers = { 'Authorization': f'Bearer {app.config["COZE_API_KEY"]}', 'Content-Type': 'application/json' } # 发送请求到Coze API try: response = requests.post( app.config['COZE_API_URL'], headers=headers, json=coze_data, timeout=30 ) response.raise_for_status() coze_response = response.json() except requests.exceptions.RequestException as e: app.logger.error(f"Coze API request failed: {str(e)}") return jsonify({"error": "Failed to communicate with Coze API"}), 500 except json.JSONDecodeError: app.logger.error("Failed to parse Coze API response") return jsonify({"error": "Invalid response from Coze API"}), 500 # 处理token消耗 tokens_used = coze_response.get('usage', {}).get('total_tokens', 100) # 默认100 # 扣除token if not deduct_tokens(user.id, tokens_used): return jsonify({"error": "Failed to deduct tokens"}), 500 # 转换为OpenAI格式 openai_response = format_to_openai(coze_response) # 缓存到Redis(1小时) redis_client.setex(cache_key, 3600, json.dumps(openai_response)) # 保存到数据库 new_cache = MessageCache( user_id=user.id, request=json.dumps(request.json), response=json.dumps(openai_response), tokens_used=tokens_used ) db.session.add(new_cache) db.session.commit() return jsonify(openai_response) # 初始化数据库 @app.before_first_request def create_tables(): db.create_all() # 创建初始管理员账户(如果不存在) admin_username = os.getenv('ADMIN_USERNAME', 'admin') admin_email = os.getenv('ADMIN_EMAIL', 'admin@example.com') admin_password = os.getenv('ADMIN_PASSWORD', 'adminpassword') if not User.query.filter_by(username=admin_username).first(): admin = User( username=admin_username, email=admin_email, password=generate_password_hash(admin_password), is_admin=True ) db.session.add(admin) db.session.commit() # 错误处理 @app.errorhandler(404) def page_not_found(e): return render_template('404.html'), 404 @app.errorhandler(500) def internal_server_error(e): return render_template('500.html'), 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)
07-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Roc-xb

真诚赞赏,手留余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值