作者:E4b9a6, 创建:2021-06-15, 字数:2214, 已阅:83, 最后更新:2021-06-15
根据官方文档 - concurrent.futures,Python支持的异步操作代码如下
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失效,如下面这样
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,将上述代码改成如下即可解决问题
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()