menu E4b9a6's blog
rss_feed
E4b9a6's blog
有善始者实繁,能克终者盖寡。

Flask执行异步操作

作者:E4b9a6, 创建:2021-06-15, 字数:2214, 已阅:70, 最后更新:2021-06-15

这篇文章更新于 1225 天前,文中部分信息可能失效,请自行甄别无效内容。

根据官方文档 - concurrent.futures,Python支持的异步操作代码如下

TEXT
import time
from concurrent.futures import ThreadPoolExecutor
def wait_on_b():
    time.sleep(5)
    print(b.result())  # b will never complete because it is waiting on a.
    return 5

def wait_on_a():
    time.sleep(5)
    print(a.result())  # a will never complete because it is waiting on b.
    return 6


executor = ThreadPoolExecutor(max_workers=2)
a = executor.submit(wait_on_b)
b = executor.submit(wait_on_a)

但遗憾的是,如果你在Flask里直接调用这个方法在涉及一些上下文操作的时候会因为丢失上下文而导致一些Flask的Function失效,如下面这样

TEXT
from concurrent.futures import ThreadPoolExecutor
from app import db_connect
executor = ThreadPoolExecutor(1)
@app.before_request
def befre_request():
    _dict = {}
    for key, value in request.__dict__['environ'].items():
        if isinstance(value, str):
            _dict[key] = value
    executor.submit(visit_record, _dict)

def visit_record(_dict):
    t_visit = TVisit(v_addr=_dict['HTTP_X_FORWARDED_FOR'], v_user_agent=_dict['HTTP_USER_AGENT'],
                     v_path=_dict['PATH_INFO'], v_original=json.dumps(_dict), create_time=datetime.datetime.now())
    db_connect.session.add(t_visit)
    db_connect.session.commit()

在方法 visit_record 中涉及到插入数据,db_connect是使用Flask初始化的,因为丢失上下文会导致数据插入数据库失败

解决这个问题是方法是引入Flask的 copy_current_request_context,将上述代码改成如下即可解决问题

TEXT
from concurrent.futures import ThreadPoolExecutor
from app import db_connect
# 改动一:引入copy_current_request_context
from flask import copy_current_request_context
executor = ThreadPoolExecutor(1)
@app.before_request
def befre_request():
    _dict = {}
    for key, value in request.__dict__['environ'].items():
        if isinstance(value, str):
            _dict[key] = value
    # 改动二:调用visit_record之前使用copy_current_request_context
    executor.submit(copy_current_request_context(visit_record), _dict)


def visit_record(_dict):
    t_visit = TVisit(v_addr=_dict['HTTP_X_FORWARDED_FOR'], v_user_agent=_dict['HTTP_USER_AGENT'],
                     v_path=_dict['PATH_INFO'], v_original=json.dumps(_dict), create_time=datetime.datetime.now())
    db_connect.session.add(t_visit)
    db_connect.session.commit()

[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
gravatar
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]