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…...
AMD GPU本地AI模型部署终极指南:ollama-for-amd让你的Radeon显卡焕发新生
AMD GPU本地AI模型部署终极指南:ollama-for-amd让你的Radeon显卡焕发新生 【免费下载链接】ollama-for-amd Get up and running with Llama 3, Mistral, Gemma, and other large language models.by adding more amd gpu support. 项目地址: https://gitcode.com/…...
避坑指南:VMware安装RockyLinux后网络不通、SSH连不上的常见问题排查与修复
Rocky Linux虚拟机网络故障排查实战指南 当你满怀期待地在VMware中安装好Rocky Linux,准备大展拳脚时,却发现网络连接失败、SSH无法访问——这种挫败感我深有体会。本文将带你直击问题核心,用系统化的排查思路解决这些"安装后困境"…...
别只当普通Office用!挖掘WPS教育考试版里那些被忽略的‘学习神器’
解锁WPS教育考试版的隐藏技能:从工具到学习伙伴的进阶指南 在备考的漫长征途中,我们常常陷入"工具只是工具"的思维定式。WPS教育考试版远不止是一个文档编辑器,它更像是一位24小时待命的学习助手,只是大多数人从未真正…...
麒麟系统离线安装PostgreSQL?手把手教你用dnf和repotrack搞定所有依赖包
麒麟系统离线部署PostgreSQL全攻略:从依赖包下载到本地仓库构建 在政企级IT基础设施中,麒麟操作系统因其安全可控的特性成为关键业务系统的首选平台。当这些系统运行在物理隔离的内网环境时,如何解决软件依赖的"最后一公里"问题&am…...
开关电源功率因数校正:从谐波失真到PFC电路设计实践
1. 项目概述:从“相移”到“失真”,理解开关整流器的功率因数挑战在通信、数据中心乃至我们日常使用的各类开关电源适配器中,高频开关整流器是电能转换的核心。作为一名电源工程师,我经常被问到:“为什么我们设备的输入…...
避开PostgreSQL逻辑复制的那些坑:从复制标识(Replica Identity)配置到性能调优指南
PostgreSQL逻辑复制深度优化:从复制标识陷阱到高性能配置实战 在数据库架构设计中,逻辑复制作为PostgreSQL的核心功能之一,为数据分发、高可用和实时分析提供了强大支持。但许多中高级用户在实际部署时,往往会在复制标识配置和性能…...
一站式PCBA制造专家:天地通22年如何赋能智能硬件产业?
公司概况与实力证明 深圳市天地通电子有限公司成立于2004年,是22年深耕电子制造的一站式PCBA服务商。公司总部位于深圳市宝安区西乡街道,毗邻宝安机场,并在深圳沙井、惠州、珠海设有生产基地,合计厂房面积超7000平方米,…...
从Wi-Fi 6到5G:深入浅出聊聊MIMO中的CSI反馈那些事儿(PMI/RI/CQI详解)
从Wi-Fi 6到5G:深入浅出聊聊MIMO中的CSI反馈那些事儿(PMI/RI/CQI详解) 现代无线通信系统正经历着从Wi-Fi 6到5G的跨越式发展,而多天线技术(MIMO)作为提升频谱效率的核心手段,其性能很大程度上依赖于准确的信道状态信息…...
告别CentOS!Debian 11 + VMware 保姆级教程:搞定那些只支持国产系统的Linux客户端(以aTrust为例)
Debian 11 VMware 全栈解决方案:无缝运行国产Linux客户端软件 在开源世界的版图中,CentOS曾经是企业级Linux的代名词,但随着Red Hat战略调整和CentOS Stream的转型,许多传统解决方案正在面临前所未有的兼容性挑战。特别是在需要对…...
从狼群狩猎到参数调优:GWO算法在机器学习超参数搜索中的保姆级指南
从狼群狩猎到参数调优:GWO算法在机器学习超参数搜索中的保姆级指南 在机器学习项目的最后阶段,我们常常会陷入超参数优化的泥潭。网格搜索耗时费力,随机搜索像买彩票,而贝叶斯优化又过于复杂。这时候,一群来自大自然的…...
