Python3 flask-socketio 整合vue

news2024/10/7 15:19:23

1. 前端说明

前端追加了vue-socket.io的依赖

更新package.json及package-lock.json后,需要补充库

2. 后端说明

服务端需要安装的python包

  • suse python 3.6.12
Flask_SocketIO-4.3.1-py2.py3-none-any.whl
python_socketio-4.6.0-py2.py3-none-any.whl
python_engineio-3.13.2-py2.py3-none-any.whl
cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
zope.event-4.6-py2.py3-none-any.whl
zope.interface-5.5.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
greenlet-1.1.3-cp36-cp36m-manylinux1_x86_64.whl
gevent_websocket-0.10.1-py3-none-any.whl
gevent-20.12.1.tar.gz
  • windows python 3.8.10
Flask_SocketIO-4.3.1-py2.py3-none-any.whl
python_socketio-4.6.0-py2.py3-none-any.whl
python_engineio-3.13.2-py2.py3-none-any.whl
zope.event-4.6-py2.py3-none-any.whl
zope.interface-6.0-cp38-cp38-win_amd64.whl
cffi-1.15.1-cp38-cp38-win_amd64.whl
greenlet-2.0.2-cp38-cp38-win_amd64.whl
gevent_websocket-0.10.1-py3-none-any.whl
 其中gevent-20.12.1.tar.gz 需要最后手动解压然后 执行setup.py  

3. whl依赖包下载

https://pypi.org/

如有网环境,可以采用以下安装方式:

先在有网环境下,PyCharm工具里面下载,如下图:

在这里插入图片描述
在这里插入图片描述

然后在无网环境下直接使用现成的即可:
在这里插入图片描述

备注:有网环境下也可采用下面的方式按照依赖

# 后端依赖安装
pip install flask-socketio
pip install flask-cors

# 前端依赖安装
npm install socket.io-client --also=dev
npm install  vue-socket.io --also=dev
npm install  echarts --also=dev

后端依赖安装

pip install flask-socketio
pip install flask-cors

前端依赖安装

npm install socket.io-client --also=dev
npm install vue-socket.io --also=dev
npm install echarts --also=dev

4. 报错问题

Linux 手动安装python setuptools时报错缺少zlib模块解决办法

python操作kafka报错:return ‘<SimpleProducer batch=%s>‘ % self.async

python ERROR: Could not find a version that satisfies the requirement XXX解决方法

【frida】lxhToolHTTPDecrypt安装使用问题

Python ThreadPoolExecutor线程池:
Python ThreadPoolExecutor线程池

5. 实现过程

前端代码

vue.config.js (只列出相关代码)

'use strict'
const path = require('path')
const defaultSettings = require('./src/settings.js')

function resolve(dir) {
  return path.join(__dirname, dir)
}

const name = defaultSettings.title || 'vue Admin Template' // page title



// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {
  /**
   * You will need to set publicPath if you plan to deploy your site under a sub path,
   * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
   * then publicPath should be set to "/bar/".
   * In most cases please use '/' !!!
   * Detail: https://cli.vuejs.org/config/#publicpath
   */
  publicPath: '/',
  outputDir: 'dist',
  assetsDir: 'static',
  lintOnSave: process.env.NODE_ENV === 'development',
  productionSourceMap: false,
  devServer: {
    host: '0.0.0.0',
    port: port,
    overlay: {
      warnings: false,
      errors: true
    },
    before: require('./mock/mock-server.js'),
    proxy: {
      // 本地使用代理  线上使用nginx
      '/dev-api/api': {
        target: `http://127.0.0.1:5100`,
        changeOrigin: true,
        onProxyReq:function (proxyReq, req, res, options) {
          if (req.body) {
            let bodyData = JSON.stringify(req.body);
            // incase if content-type is application/x-www-form-urlencoded -> we need to change to application/json
            proxyReq.setHeader('Content-Type','application/json');
            proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
            // stream the content
            proxyReq.write(bodyData);
          }
        },
        pathRewrite: {
          '^/dev-api/api': '/api'
        }
      },
      '/dev-api/upload/api': {
        target: `http://127.0.0.1:5100`,
        changeOrigin: true,
        onProxyReq:function (proxyReq, req, res, options) {
          if (req.body) {
            let bodyData = JSON.stringify(req.body);
            proxyReq.write(bodyData);
          }
        },
        pathRewrite: {
          '^/dev-api/upload/api': '/api'
        }
      },
      '/socket.io': {
        target: `http://127.0.0.1:5100`,
        ws: true,
        changeOrigin: true
       },
    }
  },
  
}

页面发起请求的按钮示例代码:

        <!-- 从架构平台同步应用系统数据-->
        <el-button type="primary" icon="el-icon-refresh" @click="updateAppList()">从架构平台同步</el-button>

import { getApplicationList, putApplicationItem, UpdateApplicationList, getApplicationDetail } from '@/api/organization'
import VueSocketIO from 'vue-socket.io'

后端代码

flask main.py

import os
import sys
import json
import time
# from crypt import methods
import queue
import xlrd
import threading
from concurrent.futures import ThreadPoolExecutor

from flask import Flask, Response, make_response, send_file, send_from_directory
from flask import request
from flask_socketio import SocketIO, send, emit

# sys.path.append("/app/app")

from service.service_websocket import update_business_list_webscoket, import_duty_info_websocket
app = Flask(__name__, instance_relative_config=True)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins="*")
executor = ThreadPoolExecutor(max_workers=2)
Swagger(app)
def update_business_list_thread(msg_queue):
    update_business_list_webscoket(msg_queue)
    
@socketio.on('connect', namespace='/update_application_list')
def connect_update_application_list():
    print("=============================update_application_list connect..")
    token = request.headers.get('X-Token')  # 获取token
    condition = {'update_by': ""}
    if token and token != '':
        user_info = get_user_data(token)
        user_id = user_info['id']
        condition['update_by'] = user_id
    print(condition)
    timeout = 120
    msg_queue = queue.Queue()
    # 在上面最开始程序中,executor = ThreadPoolExecutor(max_workers=2)
    # 表示创建一个线程池,而它的管理者就是实例对象executor,executor有一个submit() 方法,
    # 它会将线程提交给线程池,与原本直接使用Thread类的多线程编程不同,线程池中的线程提交后,若线程数量不超过max_workers,就会启动新提交的线程,
    # 而使用Thread类需要调用start() 方法去启动

    # 在执行update_business_list_webscoket(msg_queue)任务期间,实时的向队列msg_queue放入当前的执行状态信息
    thread = executor.submit(update_business_list_thread, msg_queue)
    #  threading.Timer 是 threading.Thread 的一个派生类,是在指定的时间 n 秒后执行一个函数功能。它会集成 threading.Thread 的很多属性和方法。
    threading.Timer(timeout, thread_timeout, args=(thread, msg_queue, ))

    # 使用 flask_socketio 默认提供的方法 start_background_task 伪同步的执行一个后台任务,该任务需要持续存在
    # 由于 app 上下文在伪同步中被保持,所以可以正确主动执行发送 emit / send
    socketio.start_background_task(target=handle_queue, namespace='update_application_list', msg_queue=msg_queue)


def thread_timeout(thread, msg_queue):
    try:
        if not thread.done():
            thread.cancel()
            msg_queue.put({'message': '应用信息同步超时', 'status': 'error'})   
    except Exception as r:
        print('未知错误 %s' % (r))

# 同时在执行的这个后台任务,一旦发现msg_queue里面有更新的状态信息,就会立即将响应返回给前端予以展示
def handle_queue(namespace, msg_queue):
    while True:
        socketio.sleep(1)
        while msg_queue.empty() == False:
            msg = msg_queue.get()
            socketio.emit(namespace, msg, namespace='/' + namespace)
            if msg['status'] == 'finished':
                print(namespace + ' is finished.')
                return

@socketio.on('connect')
def connect():
    print("=============================connect..")
    # socketio.emit("response", {'percentage': 18})

@socketio.on('disconnect')
def disconnect():
    print("===========================disconnect...")
    
@socketio.on_error()        # Handles the default namespace
def error_handler(e):
    print('=====================received error: ' + str(e))
    pass

@socketio.on_error_default  # handles all namespaces without an explicit error handler
def default_error_handler(e):
    print('=====================received error: ' + str(e))
    pass




if __name__ == '__main__':

    app.config.from_mapping(
        SECRET_KEY='dev',
        # DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
    )

    # if test_config is None:
    #     # load the instance config, if it exists, when not testing
    #     app.config.from_pyfile('config.py', silent=True)
    # else:
    #     # load the test config if passed in
    #     app.config.from_mapping(test_config)

    # ensure the instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    socketio.run(app, port=port_flask, host="0.0.0.0")

6. 效果演示:

先简单构造一个测试数据:
在这里插入图片描述

下面开始发起请求:
在这里插入图片描述

后端代码Print打印出来日志如下:
在这里插入图片描述

前端请求栏详细信息如下:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

可以看到下面的时间间隔为15秒左右:
在这里插入图片描述

7. 参考文章:

vue使用 vue-socket.io三种方式及踩坑实例解析

https://github.com/xugaoxiang/FlaskTutorial

python socketio 服务器编程:

http://www.taodudu.cc/news/show-5726096.html?action=onClick

python socketio 服务器编程 源码:

https://github.com/yicaifenchen8/socketio

其他了解一下:

Flask教程(十九)SocketIO:

https://blog.csdn.net/djstavaV/article/details/112261889

Flask-SocketIO 中文文档:

http://juzizhou.net/article/112

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/632601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在PPT里如何做出晶莹剔透的高级水泡感出来呢

开篇 很多PPT特别是一些TED演讲类PPT,它的首页开篇给人以强烈的冲击感。比如说上面这张PPT,笔者就卖出过一页800元的效果。它的高级高级在以下两个地方: 水晶感;透明感这是时下非常流行的一种TED场景式演讲专用的PPT,适用于一些大厂的CTO、CEO都大量使用这种效果。 今天…

shell脚本编写辅助命令

目录 一、echo 命令 二、字符串相关操作 1.截取字符串 2.获取字符串长度 3.字符串追加字符 4.从开头或结尾删除字符串指定格式内容 三、随机数 1.使用 $RANDOM 2.指定RANDOM变量的范围 &#xff08;1&#xff09;从0开始的范围 &#xff08;2&#xff09;从指定数始…

35、git的使用

一、git简介 git是一款免费、开源的版本控制系统&#xff0c;用于高效地处理任何或大或小的项目。 作用&#xff1a; 文件存档备份 文件版本管理 多人协同合作&#xff08;自动合并&#xff09; 二、git的三个区域 工作区&#xff1a;处理工作的区域 暂存区&#xff1a;临时存放…

Shell脚本实现数组冒泡排序等简单算法排序

目录 一、冒泡排序 1.简介 2.基本思想 3.算法思路 4.shell脚本实现 二、选择排序 1.简介 2.基本思想 3.shell脚本实现 三、插入排序 1.算法思路 2.shell脚本实现 四、反转排序 1.作用 2.shell脚本实现 一、冒泡排序 1.简介 类似气泡上涌的动作&#xff0c;会将…

Java入门之学习随记(三)

一. 栈内存和堆内存 堆内存:存放"引用数据类型的数据"和"new出来的对象",注意-创建出来的对象只包含各自的成员变量,不包括成员方法. 栈内存:存放"基本数据类型的数据","引用数据类型的变量名"以及"对象的引用",但是引用数…

k8s之ReplicaSet回收pod的优先级

ReplicaSet syncReplicaSet的逻辑&#xff0c;首先找到rs下相关的pod // 从informer中获取当前ns下所有的podallPods, err : rsc.podLister.Pods(rs.Namespace).List(labels.Everything())if err ! nil {return err}// 忽略不健康的podfilteredPods : controller.FilterActiveP…

CentOS桥接模式下设置静态IP并解决java.net.ConnectException: Connection timed out: connect

一、前言 最近在配置服务器&#xff0c;DHCP模式下IP地址不固定&#xff0c;每次SSH远程登录连接不上&#xff0c;都要查看新动态分配的IP地址重新配置&#xff0c;感觉些许麻烦&#xff0c;于是给机器配置了静态固定IP。 动态主机配置协议DHCP&#xff08;Dynamic Host Confi…

Shell脚本练习题(附详细解题过程)

目录 一、利用for循环打印99乘法表 二、十进制转二进制 三、将十进制ip地址转换为二进制格式 四、检测某个网段中存活的主机并输出其ip地址 五、检查文件中用户名是否存在并提示创建用户和设置密码 六、检查httpd服务并开启 七、根据百米赛跑成绩判断结果 八、随机数…

栈和队列(数据结构刷题)[一]-python

文章目录 前言一、原理介绍二、用栈实现队列1.操作2.思路 三、关于面试考察栈里面的元素在内存中是连续分布的么&#xff1f; 前言 提到栈和队列&#xff0c;大家可能对它们的了解只停留在表面&#xff0c;再深入一点&#xff0c;好像知道又好像不知道的感觉。本文我将从底层实…

Django----------模板、静态文件、案例(城市天气预报)、请求和响应

目录 1.templates模板 2.静态文件 1.static目录 2.引用静态文件 1.方式一&#xff1a;直接引用 2.方式二&#xff1a;头部及内部引用 3. 模板语法 1.取内容 2.取下标 3.for循环 4.利用字典 5.列表里套字典 6.if条件语句 7.总结 4.案例&#xff08;城市天气预…

CH573-01-GPIO-LED——RISC-V内核BLE MCU快速开发教程

1. 新建工程 1) NEW Project 点击“File->New->MounRiver Project”&#xff1a; 2) finish 选择CH573F的裸机开发工程模板&#xff0c;如下图&#xff0c;然后点击“finish” 3) 编译检查 4) 精简代码 打开工程目录下的./src/main.c文件&#xff0c;修改删掉生成的串口测…

动态规划III (买股票-121、122、123、188)

CP121 买股票的最佳时机 题目描述&#xff1a; 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利…

Vue 中的几种动画效果

Vue 中的动画效果 在 Vue 中&#xff0c;动画效果是非常常见的交互方式。它可以为用户提供更加生动的交互体验&#xff0c;增强用户的参与感和满意度。在本文中&#xff0c;我们将探讨 Vue 中的动画效果的基本原理和用法&#xff0c;并给出一些实例代码来帮助读者更好地理解。…

『手撕 Mybatis 源码』06 - Mapper 代理方式初始化

Mapper 代理方式初始化 首先修改一下 SqlSession 获取代理对象方式&#xff0c;即通过 getMapper() 来拿到动态代理对象 public class MybatisTest {/*** 问题1&#xff1a;<package name"com.itheima.mapper"/> 是如何进行解析的&#xff1f;* 解答&#xf…

算法刷题-数组-有序数组的平方

977.有序数组的平方 力扣题目链接 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 示例 1&#xff1a; 输入&#xff1a;nums [-4,-1,0,3,10] 输出&#xff1a;[0,1,9,16,100] 解释&#…

clang到底是什么?gcc和clang到底有什么区别?

最近发现自己对 GNU GCC 和 Clang 的区别不太清楚&#xff0c;影响到一些实现和学习&#xff0c;所以趁这两天有空好好研究了一下。 在这个研究过程中&#xff0c;我发现很多问题其实源自于语言&#xff08;不是指编程语言&#xff0c;而是中文和英文翻译的失真&#xff09;和…

前端前端学习不断

卷吧卷吧...&#xff0c;这东西什么时候是个头啊……

智能指针(2)

智能指针&#xff08;2&#xff09; shared_ptr(共享型智能指针)基础知识特点引用计数器共享型智能指针结构理解 shared_ptr仿写删除器类计数器类shared_ptr类使用以及仿写代码的理解 循环引用_Weaks 初始化智能指针的方法 shared_ptr(共享型智能指针) 基础知识 在java中有一…

chatgpt赋能python:Python如何判断输入的字符——基础教程与实例

Python如何判断输入的字符——基础教程与实例 时至今日&#xff0c;互联网已经成为人们获取信息的重要途径&#xff0c;而搜索引擎优化&#xff08;SEO&#xff09;则是网站重要的推广手段之一。而Python作为一种高级编程语言&#xff0c;在实现SEO时也有很大的优势&#xff0…

chatgpt赋能python:Python如何进行升序和降序排列

Python如何进行升序和降序排列 Python是一种非常流行的编程语言&#xff0c;由于其在数据科学、机器学习和人工智能等领域的强大表现&#xff0c;越来越多的人开始学习和使用Python。在Python中&#xff0c;排序是一项非常常见的操作。在这篇文章中&#xff0c;我将向您介绍如…