专栏首页python前行者[750]flask之异步非堵塞实现

[750]flask之异步非堵塞实现

  • 同步:是指完成事务的逻辑,先执行第一个事务,如果阻塞了,会一直等待,直到这个事务完成,再执行第二个事务,顺序执行
  • 异步:是和同步相对的,异步是指在处理调用这个事务的之后,不会等待这个事务的处理结果,直接处理第二个事务去了,通过状态、通知、回调来通知调用者处理结果

定义了一个装饰器 async 和 A 、B 两个function 函数,A 里面sleep 10s , 然后打印 a function 字符串 ,B 里面直接打印 b function 字符串 ,我们顺序调用两个功能: A() ,B( )

由于函数A在睡的状态,我们又不希望程序被阻塞在函数A的睡的状态,所以我们采用异步执行,即在函数A睡的状态,让其他的任务执行

from threading import Thread
from time import sleep


def async(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target=f, args=args, kwargs=kwargs)
        thr.start()
    return wrapper

@async
def A():
    sleep(10)
    print("函数A睡了十秒钟。。。。。。")
    print("a function")

def B():
    print("b function")

A()
B()

执行结果:

b function
函数A睡了十秒钟。。。。。。
a function

1、通过设置app.run()的参数,来达到多线程的效果,具体参数:

# 1、threaded : 多线程支持,默认为False,即不开启多线程;
app.run(threaded=True)
# 2、processes:进程数量,默认为1.
app.run(processes=True)
ps:多进程或多线程只能选择一个,不能同时开启

2、解决方案: flask+gevent

安装gevent

pip install gevent
pip install gevent-websocket
pip install flask

修改代码

# -*- coding:utf-8 -*-
import time,asyncio
from flask import Flask,request,Response
from gevent import monkey
from gevent.pywsgi import WSGIServer
# 在玩websockets,可以无视之哈,有空贴下flask websockets实现哈
from geventwebsocket.handler import WebSocketHandler #pip install gevent-websocket


#gevent的猴子魔法
monkey.patch_all()

app = Flask(__name__)
# app.config.update(DEBUG=True)


@app.route('/asyn/1/', methods=['GET'])
def test_asyn_one():
    if request.method == 'GET':
        asyncio.sleep(10)
        return 'hello asyn'


@app.route('/test/', methods=['GET'])
def test():
    return 'hello test'


if __name__ == "__main__":
    """
   使用flask自带的传递参数threaded与processes,也可以实现异步非阻塞,但是这个原理是
   同时开启多个线程或者多个进程来接受发送的请求,每个线程或者进程还是阻塞式处理任务
   如果想使用threaded或processes参数,必须将debug设置为False才能生效,不然不起作用
   同时Windows下不支持同时开启多进程,所以在win下使用processes无效
    """
    # app.run(host='0.0.0.0', port=10008, debug=False, threaded=True, processes=5)
    http_server = WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
    http_server.serve_forever()

运行之后可以先访问/asyn/1/再访问/test/,可以明显发现,/asyn/1/在做耗时任务时不会影响其他请求

关于monkey.patch_all()

为什么要加monkey.patch_all()这一条语句呢?在gevnet的官网有详细的解释,这里简单说明一下:

monkey carefully replace functions and classes in the standard socket module with their cooperative counterparts. That way even the modules that are unaware of gevent can benefit from running in a multi-greenlet environment.

翻译:猴子补丁仔细的用并行代码副本替换标准socket模块的函数和类,这种方式可以使模块在不知情的情况下让gevent更好的运行于multi-greenlet环境中。


Flask 依赖两个外部库: Jinja2 模板引擎和 Werkzeug WSGI 套件

@flask_script扩展

  1. 安装:pip install flask-script
  2. 说明: 在项目测试完成后,上线时最好不要改动任何代码。只能通过终端的方式进行启动,通过传递不同的参数,完成特定的启动方式。很遗憾flask默认不支持命令行启动,然而幸运(_)的是有一个第三方库flask-script帮我们实现了这个功能。简单来说,它就是一个flask终端启动的命令行解析器。
  3. 使用:
# 导入类库
from flask_script import Manager
# 创建对象
manager = Manager(app)
# 启动应用实例
if __name__ == '__main__':
    #app.run(debug=True, threaded=True, port=8000, host='0.0.0.0')
    manager.run()

启动参数

-?,–help # 查看帮助信息 –threaded # 开启多线程 -d # 开启调试模式 -r # 自动加载 -h,–host # 指定主机 -p,–port # 指定端口

在命令行使用

python manage.py runserver -d -r -p 8000 -h 0.0.0.0 

开启多线程

python manage.py runserver -p 8000 -h 0.0.0.0 --threaded

参考: https://www.cnblogs.com/sui776265233/p/10950001.html https://blog.csdn.net/danny_amos/article/details/50859383 https://blog.csdn.net/yannanxiu/article/details/52915929 https://blog.csdn.net/u012089823/article/details/85264084 https://www.jianshu.com/p/79489cfc6fb9 https://blog.csdn.net/qq_39222965/article/details/80654546

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python将html转化为pdf

    前面我们对博客园的文章进行了爬取,结果比较令人满意,可以一下子下载某个博主的所有文章了。但是,我们获取的只有文章中的文本内容,并且是没有排版的,看起来也比较费劲...

    周小董
  • Python3之PrettyTable模块(美化库)

    参考:https://blog.csdn.net/u013630675/article/details/78773356

    周小董
  • Python库简单说明(持续更新...)

    目前,网上已有成千上万个Python包,但几乎没有人能够全部知道它们。单单 PyPi上就有超过47000个包列表。

    周小董
  • flask+gevent+uwsgi部署

    马哥Python
  • flask 脚本运行

    from flask import Flask from flask import abort from flask_script import Manag...

    用户5760343
  • python 生成flask结构 常用

    config=""" import os basedir = os.path.abspath(os.path.dirname(file)) class C...

    用户5760343
  • Flask入门之完整项目搭建

      在application/__init__.py项目初始化文件中加载redis或者mysql的初始化代码

    py3study
  • 彻底搞懂Python 中的 import 与 from import

    对不少 Python 初学者来说,Python 导入其他模块的方式让他们很难理解。什么时候用import xxx?什么时候用from xxx import yy...

    青南
  • flask 获取request信息

    from flask import Flask from flask import request

    用户5760343
  • Nest.js 从零到壹系列(一):项目创建&路由设置&模块

    本系列将以前端的视角进行书写,分享自己的踩坑经历。教程主要面向前端或者毫无后端经验,但是又想尝试 Node.js 的读者,当然,也欢迎后端大佬斧正。

    一只图雀

扫码关注云+社区

领取腾讯云代金券