flask框架-[实现websocket]:将socketio处理函数部分集中管理,使用类的方式来管理,集中管理socketio处理函数
一、项目依赖
APScheduler==3.10.4
eventlet==0.33.3
Flask==2.1.3
Flask-Caching==1.10.1
Flask-Cors==3.0.10
Flask-Migrate==2.7.0
Flask-RESTful==0.3.9
Flask-SocketIO==5.1.1
Flask-SQLAlchemy==2.5.1
PyJWT==2.3.0
PyMySQL==1.0.2
redis==3.5.3
SQLAlchemy==1.4.0 #额外修改
Werkzeug==2.0.2 #额外修改
注意:在flask2.x版本依赖,不再支持flask_script了
flask2.x版本会自动注册 flask run 和flask db 两个命令行命令
1、启动项目
flask run --host 0.0.0.0 --port 9000
2、数据库迁移命令
flask db init
flask db migrate
flask db upgrade
二、项目结构
apps
__init__.py : 创建app应用,各种注册
websocket
consumers.py #将所有socketio处理类放到这里
base
settings.py
ext
__init__.py: 拓展对象都放在这里
config.py : 拓展对象的配置内容
app.py
三、具体代码使用
settings.py
import os
import datetime
def get_database(dic):'"mysql+pymysql://root:Huawei@123@localhost:3306/study_flask?charset=utf8"'engine = dic.get('ENGINE')driver = dic.get('DRIVER')user = dic.get('USER')host = dic.get('HOST')password = dic.get("PASSWORD")port = dic.get('PORT')name = dic.get('NAME')dbinfo = f"{engine}+{driver}://{user}:{password}@{host}:{port}/{name}?charset=utf8"return dbinfo#全局通用配置类
class Config:"""项目配置核心类"""DEBUG=TrueLOG_LEVEL = "INFO"SECRET_KEY= '8hdj^sasdas6736475#$#5&GHG'BASE_PATH = os.path.dirname(os.path.abspath(__file__))STATIC_PATH = os.path.join(BASE_PATH, 'static') #static/ 路由对应的目录TEMPLATES_PATH = os.path.join(BASE_PATH, 'templates') # 用于专门检索静态文件的位置,方便修改# 中文乱码JSON_AS_ASCII = False# # 配置redis# # 项目上线以后,这个地址就会被替换成真实IP地址,mysql也是# REDIS_HOST = 'your host'# REDIS_PORT = your port# REDIS_PASSWORD = 'your password'# REDIS_POLL = 10#数据库配置dbinfo={'ENGINE':'mysql','DRIVER':'pymysql','USER':'root','PASSWORD':'123456','HOST':"127.0.0.1","PORT":"3306",'NAME':'flask_obj'}# 数据库连接格式SQLALCHEMY_DATABASE_URI = get_database(dbinfo)# 动态追踪修改设置,如未设置只会提示警告SQLALCHEMY_TRACK_MODIFICATIONS = False# 查询时会显示原始SQL语句SQLALCHEMY_ECHO = False# 数据库连接池的大小SQLALCHEMY_POOL_SIZE=100#指定数据库连接池的超时时间SQLALCHEMY_POOL_TIMEOUT=30# 控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。SQLALCHEMY_MAX_OVERFLOW=2#配置日志时,需要设置False,只能flask才能捕获移除写到日志文件中PROPAGATE_EXCEPTIONS = False#配置时区TIMEZONE = local_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfoclass DevConfig(Config):DEBUG = Trueclass TestConfig(Config):DEBUG = Trueclass Online(Config):DEBUG = Falseenvs = {'dev':DevConfig,'test':TestConfig,'online':Online,'default':Config
}
3.1、ext配置
1、ext/__init__.py
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from flask_restful import Api
from flask_caching import Cache
from flask_socketio import SocketIOdb = SQLAlchemy() #数据库对象
cors = CORS() #跨域
cache = Cache() #缓存
socketio = SocketIO()#websocket对象
2、ext/config.py
#跨域的配置
cors_config = {"origins": "*", #所有域都允许"expose_headers": ["Content-Type", "token","x-requested-with"], #跨域请求头允许的"methods": ["GET", "POST","PUT","PATCH","OPTIONS","DELETE"], #跨域允许的请求方式"supports_credentials": True, #允许在cookies跨域
}#cache缓存配置-使用redis数据库
cache_config_redis = {'CACHE_TYPE':'redis','CACHE_REDIS_HOST':'127.0.0.1','CACHE_REDIS_PORT':6637,# 'CACHE_REDIS_PASSWORD':'密码', #如果redis配置了密码'CACHE_REDIS_DB':0, #指定使用的redis的db,默认0-15
}#cache缓存配置-使用内存
cache_config_mem = {'CACHE_TYPE':'simple'#使用内存作为cache
}
3.2、apps配置
1、__init__.py
import logging
import eventlet
from flask import Flask,jsonify#导入跨域对象
from ext import cors
#导入db对象
from ext import db
#导入cache
from ext import cache
#导入socketio
from ext import socketio
#导入拓展的配置内容
from ext.config import cache_config_redis,cache_config_mem,cors_config#导入中间件
from base.middleware import after_request #响应前执行的中间件#导入配置字典
from base.settings import envs#导入日志
from base.logger import getLogHandlerFile
from base.logger import getLogHanderTime#定时任务
from base.scheduler import SchedulerManage#注册socketio的命名空间
from apps.websocket.consumers import TotalWebsocketNamespace#导入蓝图
from apps.user.urls import user_bpdef create_app():#创建一个flask实例,传递__name__ ,是把当前文路径作为flask实例的根路径#static和templates都是创建在该路径下的app = Flask(__name__,static_folder='../static',template_folder='../templates') #static目录位置是上层的staticeventlet.monkey_patch() # 开启补丁机制'基本配置'#导入配置从类中app.config.from_object(envs.get('default'))'日志配置'app.logger.addHandler(getLogHanderTime()) #基于时间app.logger.addHandler(getLogHandlerFile()) #基于文件大小app.logger.setLevel(logging.INFO)'中间件'#每次响应前都先设置好响应头,做好跨域app.after_request(after_request) #【1、使用中间件解决跨域】#执行请求处理前的中间件,# app.before_request(before_request)'拓展配置'#配置db对象 将db对象与app进行绑定,orm对象与app绑定db.init_app(app)#配置跨域,supports_credentials=True 允许携带cookies等信息cors.init_app(app,**cors_config) #【2、使用三方扩展解决跨域】#配置缓存cache.init_app(app=app,config=cache_config_mem)#配置socketiosocketio.init_app(app,cors_allowed_origins='*')'socketio注册命名空间的位置: 必须在这个py文件中注册'socketio.on_namespace(TotalWebsocketNamespace('/')) #使用默认的全局名称空间'蓝图注册'app.register_blueprint(user_bp)'异常处理'@app.errorhandler(Exception)def handle_exception(e):# 将异常错误写到日志文件中app.logger.exception(str(e))# print(e, type(e))# 对异常错误的响应,使用api的格式return jsonify(code=500, message=str(e)), 500'定时任务'# SchedulerManage()return app
在本文中,最重要的就是将socketio命名空间的注册,放到create_app函数中了。
2、websocket/consumers.py
from flask import render_template, request, jsonify
from flask_socketio import SocketIO, send, emit, join_room
from ext import socketio
from flask_socketio import Namespace
'''
一、非群聊功能,前端需要实时更新某些数据使用
1、返回html页面
2、主动发送websocket到后端,后端返回数据给请求的用户
3、调用某个视图函数,在视图函数中,给所有连接推送新的数据
'''class TotalWebsocketNamespace(Namespace):def on_handle_data(self,data):print(data, '接收浏览器发送的数据')# 1、给发送给后端的websocket,发送数据,单独给这个websocket发送# socketio.emit('handle_data', {'data':'返回的数据','type':'user','msg':'单独返回'})emit('handle_data', {'data': '返回的数据', 'type': 'user', 'msg': '主动请求时,返回的数据'})def on_connect(self):print('connect连接')token = request.args.get('token')sid = request.sidprint(request.args, 'args')# print('连接的sid',request.sid)if token == '123456':socketio.emit('success', '验证token成功')join_room('default') # 加入到默认的房间中了# 表明连接成功else:print('token验证失败')# 阻止连接return False
四、总结
如何将socketio处理函数集中管理,将所有的处理类集中到一个py文件中。
1、创建一个包,在包中创建一个py文件,将所有处理socketio的类都写在这里
2、在创建flask的app应用中,注册socketio的命名空间:在create_app函数中,注册命名空间
'socketio注册命名空间的位置: 必须在这个py文件中注册'
socketio.on_namespace(TotalWebsocketNamespace('/')) #使用默认的全局名称空间
建议采用这种方式来管理socketio,在后续的维护会比较容易,拓展起来也简单。不建议使用函数的方式,这样就必须将函数都写在app.py文件中,不然后端无法监听到前端发送的websocket的请求。
五、错误写法
1、直接在consumers.py同级目录下创建一个routings.py,将命名空间的注册写到该py文件中,这样后端是无法接收到前端的websocket请求的。
2、使用函数的方式来处理逻辑,且把函数都集中放到了websocket/consumers.py文件中,这样后端是无法接收到前端的websocket请求的。
相关文章:
flask框架-[实现websocket]:将socketio处理函数部分集中管理,使用类的方式来管理,集中管理socketio处理函数
一、项目依赖 APScheduler3.10.4 eventlet0.33.3 Flask2.1.3 Flask-Caching1.10.1 Flask-Cors3.0.10 Flask-Migrate2.7.0 Flask-RESTful0.3.9 Flask-SocketIO5.1.1 Flask-SQLAlchemy2.5.1 PyJWT2.3.0 PyMySQL1.0.2 redis3.5.3 SQLAlchemy1.4.0 #额外修改 Werkzeug2.0.2 #额外修…...
Vue的学习补充
1.Vue路由-404 作用:当路径找不到匹配时,给个提示页面 位置:配在路由最后 语法:path:*(任意路径)-前面不匹配就命中最后这个 2.Vue路由-模式设置 hash路由(默认) 例如ÿ…...
vue移动端H5调起手机发送短信(兼容ios和android)
移动端h6页面调起手机发送短信功能,ios和android的兼容写法不一样。 android window.location.href sms:10086?body${encodeURIComponent(Hello, 测试短信发送)} ios window.location.href sms:10086&body${encodeURIComponent(Hello, 测试短信发送)}//或者w…...
spring boot RabbitMq基础教程
RabbitMq 由于RabbitMQ采用了AMQP协议,因此它具备跨语言的特性。任何语言只要遵循AMQP协议收发消息,都可以与RabbitMQ交互。并且RabbitMQ官方也提供了各种不同语言的客户端。 但是,RabbitMQ官方提供的Java客户端编码相对复杂,一般…...
springboot vue 部署至Rocky(Centos)并自启,本文部署是若依应用
概述 1、安装nohup(后台进程运行java) 2、安装中文字体(防止中文乱码) 3、安装chrony(保证分布式部署时间的一致性) 5、安装mysql数据,迁移目录,并授权自启动; 6、安…...
Mysql之增删改查
这篇文章旨在介绍mysql的增删改查中的基本操作 所有命令皆是以分号(;)结尾。 1.显示命令 在写增的有关命令前,我们更应该知道如何显示,这样有助于更好的检查我们的结果是否正确。 #显示数据库列表 show databases;#…...
【考研数学】矩阵三大关系的梳理和讨论 | 等价、相似、合同
文章目录 引言一、定义二、判别法写在最后 引言 昨天学了矩阵的合同关系,老汤讲义里也列举了三大关系的定义和判别法,方便我们进行区分。但是光看还是难以入脑,为此,我想自己梳理一遍,顺带也复习一下线代之前的所学。…...
在 Amazon SageMaker 上使用 ESMFold 语言模型加速蛋白质结构预测
蛋白质驱动着许多生物过程,如酶活性、分子输运和细胞支持。通过蛋白质的三维结构,可以深入了解蛋白质的功能以及蛋白质如何与其他生物分子相互作用。测定蛋白质结构的实验方法(如 X 射线晶体学和核磁共振波谱学)既昂贵又耗时。相比…...
node.js知识系列(4)-每天了解一点
目录 11. 异步文件操作文件读取文件写入 12. 包管理器(npm)13. 子进程14. 事件发射器(EventEmitter)15. 异步编程和回调16. Node.js 集成测试工具和框架17. Express.js 中间件的 HTTP 请求流程18. 文件上传和验证19. Express.js 中…...
can not remove .unionfs
文件夹下出现unionfs 套娃,无法删除。 处理方式: 需要管理员权限umount之后删除使用fusermount -zu .unionfs ,然后再删除。...
微服务 BFF 架构设计
在现代软件开发中,由于程序、团队、数据规模太大,需要把企业的业务能力进行复用,将领域服务剥离,提供通用能力,避免重复建设和代码;另外服务功能的弹性能力不一样,比如定时任务、数据同步明确的…...
零基础学python之元组
文章目录 元组1、元组的应用场景2、定义元组3、元组的常见操作4、总结 元组 目标 元组的应用场景定义元组元组常见操作 1、元组的应用场景 思考:如果想要存储多个数据,但是这些数据是不能修改的数据,怎么做? 答:列…...
11. SpringBoot项目中参数获取与响应
SpringBoot项目中参数获取与响应 1. 程序结构&通信方式 程序结构: C/S : 客户端/服务器端 -Main方法。 -效果炫目、数据相对安全。 -公司成本高,因为要分别开发客户端和服务器端。 B/S: 浏览器端/服务器端 -效果依赖于浏览…...
4+1视图与UML
目录 逻辑视图过程视图开发视图物理视图(部署视图)用例视图 41视图,即逻辑视图,过程视图,实现视图,部署视图,用例视图。 为什么不用一个视图? 针对多个用户,即终端用户&a…...
没用的知识增加了,尝试用文心实现褒义词贬义词快速分类
尝试用文心实现褒义词贬义词快速分类 一、我的需求二、项目环境搭建千帆SDK安装及使用流程 三、项目实现过程创建应用获取签名调用接口计算向量积总结 百度世界大会将于10月17日在北京首钢园举办,今天进入倒计时五天了。通过官方渠道的信息了解到,这次是…...
AWS SAP-C02教程3--网络资源
架构设计中网络也是少不了的一个环节,而AWS有自身的网络结构和网络产品。本章中将带你看看AWS中不同网络产品,以及计算资源、存储资源等产品在网络架构中处于哪个位置,如何才能让它们与互联网互通、与其它产品互通。下图视图将SAP涉及到网络相关组件在一张图表示出来,图中可…...
【TensorFlow2 之012】TF2.0 中的 TF 迁移学习
#012 TensorFlow 2.0 中的 TF 迁移学习 一、说明 在这篇文章中,我们将展示如何在不从头开始构建计算机视觉模型的情况下构建它。迁移学习背后的想法是,在大型数据集上训练的神经网络可以将其知识应用于以前从未见过的数据集。也就是说,为什么…...
mysql面试题46:MySQL中datetime和timestamp的区别
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:MySQL中DATETIME和TIMESTAMP的区别 在MySQL中,DATETIME和TIMESTAMP是两种用于存储日期和时间的数据类型。虽然它们都可以用于存储日期和时间信息…...
【Spring Boot】RabbitMQ消息队列 — RabbitMQ入门
💠一名热衷于分享知识的程序员 💠乐于在CSDN上与广大开发者交流学习。 💠希望通过每一次学习,让更多读者了解我 💠也希望能结识更多志同道合的朋友。 💠将继续努力,不断提升自己的专业技能,创造更多价值。🌿欢迎来到@"衍生星球"的CSDN博文🌿 🍁本…...
Navicat定时任务
Navicat定时任务 1、启动Navicat for MySQL工具,连接数据库。 2、查询定时任务选项是否开启 查询命令:SHOW VARIABLES LIKE ‘%event_scheduler%’; ON表示打开,OFF表示关闭。 打开定时任务命令 SET GLOBAL event_scheduler 0; 或者 SET G…...
基于AkShare构建A股基础数据自动化采集方案
1. 为什么需要自动化采集A股基础数据 做量化研究的朋友都知道,获取准确、完整的股票基础数据是策略开发的基石。我刚开始做量化时,最头疼的就是每次跑策略前都要手动更新股票列表,经常因为数据不全导致回测结果失真。后来发现AkShare这个宝藏…...
【小白友好】Qwen2.5-VL-7B-Instruct快速上手:无需代码的图文智能问答工具
Qwen2.5-VL-7B-Instruct快速上手:无需代码的图文智能问答工具 1. 工具简介 Qwen2.5-VL-7B-Instruct是一款基于阿里通义千问多模态大模型的视觉交互工具,专为RTX 4090显卡优化。它最大的特点是完全可视化操作,无需编写任何代码就能实现强大的…...
Nginx + FFmpeg 核心配置
Nginx FFmpeg 核心配置(2 种最实用方案)我给你最简、能直接用的配置,不用你自己改半天,分两种场景:Nginx 接收 FFmpeg 推流(直播)Nginx 调用 FFmpeg 自动转码(高清 / 标清ÿ…...
Obsidian表格处理革新:Excel插件的无缝集成方案
Obsidian表格处理革新:Excel插件的无缝集成方案 【免费下载链接】obsidian-excel 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-excel 在知识管理的日常工作中,你是否经常遇到这样的困境:在Obsidian中记录项目数据时&#…...
Anthropic 又双叒翻车了:Claude Code源代码打包失误,这已经是第几次了?
今天(2026-03-31)上午,Anthropic的Claude Code CLI又出大糗了。 安全研究员 Chaofan Shou发现: 他们的 npm 包里多塞了一个 60MB 的 cli.js.map 文件。 结果呢?完整源代码直接公开——1900多个 TypeScript 文件&#x…...
Node.js——util工具模块
util工具模块1、util模块概述2、util模块的使用2.1、格式化输出字符串2.2、将对象转换为字符串(调试)2.3、实现对象间的原型继承2.4、转换异步函数的风格2.5、判断是否为指定类型的内置对象2.6、其它方法1、util模块概述 util模块是Node.js的内置模块&a…...
C++ ONNX Runtime推理踩坑记:为什么我的全局Session一Run就报ORT_RUNTIME_EXCEPTION?
C ONNX Runtime推理异常解析:全局Session与Env生命周期的陷阱 在C项目中使用ONNX Runtime进行模型推理时,许多开发者都遇到过这样一个令人困惑的场景:明明代码逻辑看起来完全正确,却在调用Session.Run()时突然抛出ORT_RUNTIME_EXC…...
N8N不只是工作流工具:手把手教你把它变成双向MCP网关,连接百度地图和AI Agent
N8N架构实战:构建双向MCP网关连接百度地图与AI Agent生态 在AI Agent技术栈中,协议桥接能力正成为系统设计的核心挑战。当Claude需要调用地图服务、Cursor尝试接入CRM数据时,传统API集成方式往往需要编写大量适配代码。而N8N通过独特的双向MC…...
Phi-3-mini-4k-instruct-gguf效果展示:q4量化下保持语义准确性的中文生成实录
Phi-3-mini-4k-instruct-gguf效果展示:q4量化下保持语义准确性的中文生成实录 1. 轻量级文本生成新选择 Phi-3-mini-4k-instruct-gguf是微软Phi-3系列中的轻量级文本生成模型GGUF版本,专为问答、文本改写、摘要整理和简短创作等场景优化。这个经过q4量…...
Phi-4-mini-reasoning快速上手:3步完成vLLM服务部署+Chainlit前端验证
Phi-4-mini-reasoning快速上手:3步完成vLLM服务部署Chainlit前端验证 1. 模型简介 Phi-4-mini-reasoning 是一个基于合成数据构建的轻量级开源模型,专注于高质量、密集推理的数据处理能力。作为Phi-4模型家族的一员,它经过专门微调以提升数…...
