Django视图函数执行,不在主线程中,直接
loop = asyncio.new_event_loop()  # 更不能loop = asyncio.get_event_loop()

会触发

RuntimeError: There is no current event loop in thread

因为asyncio程序中的每个线程都有自己的事件循环,但它只会在主线程中为你自动创建一个事件循环。所以如果你asyncio.get_event_loop在主线程中调用一次,它将自动创建一个循环对象并将其设置为默认值,但是如果你在一个子线程中再次调用它,你会得到这个错误。相反,您需要在线程启动时显式创建/设置事件循环:

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) 在Django单个视图中使用asyncio实例代码如下(有多个IO任务时)

  

from django.views import View
import asyncio
import time
from django.http import JsonResponse class TestAsyncioView(View):
def get(self, request, *args, **kwargs):
"""
利用asyncio和async await关键字(python3.5之前使用yield)实现协程
"""
start_time = time.time()
loop = asyncio.new_event_loop() # 或 loop = asyncio.SelectorEventLoop()
asyncio.set_event_loop(loop)
self.loop = loop
try:
results = loop.run_until_complete(self.gather_tasks())
finally:
loop.close()
end_time = time.time()
return JsonResponse({'results': results, 'cost_time': (end_time - start_time)}) async def gather_tasks(self):
"""
也可以用回调函数处理results
task1 = self.loop.run_in_executor(None, self.io_task1, 2)
future1 = asyncio.ensure_future(task1)
future1.add_done_callback(callback) def callback(self, future):
print("callback:",future.result())
"""
tasks = (
self.make_future(self.io_task1, 2),
self.make_future(self.io_task2, 2)
)
results = await asyncio.gather(*tasks)
return results async def make_future(self, func, *args):
future = self.loop.run_in_executor(None, func, *args)
response = await future
return response """
# python3.5之前无async await写法
import types
@types.coroutine
# @asyncio.coroutine # 这个也行
def make_future(self, func, *args):
future = self.loop.run_in_executor(None, func, *args)
response = yield from future
return response
""" def io_task1(self, sleep_time):
time.sleep(sleep_time)
return 66 def io_task2(self, sleep_time):
time.sleep(sleep_time)
return 77

  

在Django单个视图中使用ThreadPoolExecutor实例代码如下(有多个IO任务时)
 
from django.views import View
import time
from concurrent.futures import ThreadPoolExecutor, as_completed class TestThreadView(View):
def get(self, request, *args, **kargs):
start_time = time.time()
future_set = set()
tasks = (self.io_task1, self.io_task2)
with ThreadPoolExecutor(len(tasks)) as executor:
for task in tasks:
future = executor.submit(task, 2)
future_set.add(future)
for future in as_completed(future_set):
error = future.exception()
if error is not None:
raise error
results = self.get_results(future_set)
end_time = time.time()
return JsonResponse({'results': results, 'cost_time': (end_time - start_time)}) def get_results(self, future_set):
"""
处理io任务执行结果,也可以用future.add_done_callback(self.get_result)
def get(self, request, *args, **kargs):
start_time = time.time()
future_set = set()
tasks = (self.io_task1, self.io_task2)
with ThreadPoolExecutor(len(tasks)) as executor:
for task in tasks:
future = executor.submit(task, 2).add_done_callback(self.get_result)
future_set.add(future)
for future in as_completed(future_set):
error = future.exception()
print(dir(future))
if error is not None:
raise error
self.results = results = []
end_time = time.time()
return JsonResponse({'results': results, 'cost_time': (end_time - start_time)}) def get_result(self, future):
self.results.append(future.result())
"""
results = []
for future in future_set:
results.append(future.result())
return results def io_task1(self, sleep_time):
time.sleep(sleep_time)
return 10 def io_task2(self, sleep_time):
time.sleep(sleep_time)
return 66
 
附tornado中不依赖异步库实现异步非阻塞
from tornado.web import RequestHandler
from concurrent.futures import ThreadPoolExecutor
class NonBlockingHandler(RequestHandler):
"""
不依赖tornado的异步库实现异步非阻塞
使用 gen.coroutine 装饰器编写异步函数,如果库本身不支持异步,那么响应任然是阻塞的。
在 Tornado 中有个装饰器能使用 ThreadPoolExecutor 来让阻塞过程编程非阻塞,
其原理是在 Tornado 本身这个线程之外另外启动一个线程来执行阻塞的程序,从而让 Tornado 变得非阻塞
"""
executor = ThreadPoolExecutor(max_workers=2) # executor默认需为这个名字,否则@run_on_executor(executor='_thread_pool')自定义名字,经测试max_workers也可以等于1 @coroutine # 使用@coroutine这个装饰器加yield关键字,或者使用async加await关键字
def get(self, *args, **kwargs):
second = yield self.blocking_task(20)
self.write('noBlocking Request: {}'.format(second)) """
async def get(self, *args, **kwargs):
second = await self.blocking_task(5)
self.write('noBlocking Request: {}'.format(second))
""" @run_on_executor
def blocking_task(self, second):
"""
阻塞任务
"""
time.sleep(second)
return second

参考 https://blog.csdn.net/qq_34367804/article/details/75046718

  https://www.cnblogs.com/zhaof/p/8490045.html

  https://stackoverflow.com/questions/41594266/asyncio-with-django

 

如何在django视图中使用asyncio(协程)和ThreadPoolExecutor(多线程)的更多相关文章

  1. 如何在Django模型中管理并发性 orm select_for_update

    如何在Django模型中管理并发性 为单用户服务的桌面系统的日子已经过去了 - 网络应用程序现在正在为数百万用户提供服务,许多用户出现了广泛的新问题 - 并发问题. 在本文中,我将介绍在Django模 ...

  2. 如何在“代码”视图中工作并充分利用 Dreamweaver 的编码功能。如 Emmet 缩写

    可通过多种方式在 Dreamweaver 中处理代码. 您可以使用“新建文档”对话框打开新的代码文件,然后开始键入您的代码. 在 Dreamweaver 中创建新的代码文件 键入时,会显示代码提示以帮 ...

  3. python并发编程之asyncio协程(三)

    协程实现了在单线程下的并发,每个协程共享线程的几乎所有的资源,除了协程自己私有的上下文栈:协程的切换属于程序级别的切换,对于操作系统来说是无感知的,因此切换速度更快.开销更小.效率更高,在有多IO操作 ...

  4. 二、深入asyncio协程(任务对象,协程调用原理,协程并发)

      由于才开始写博客,之前都是写笔记自己看,所以可能会存在表述不清,过于啰嗦等各种各样的问题,有什么疑问或者批评欢迎在评论区留言. 如果你初次接触协程,请先阅读上一篇文章初识asyncio协程对asy ...

  5. 一、初识asyncio协程

    初识asyncio协程 一.基本概念 ​ 要想了解学习协程相关知识要先对以下几个概念先行了解: 阻塞 ​ 阻塞状态是指程序未得到某所需计算资源时的挂起状态,简单说就是程序在等待某个操作未执行完前无法执 ...

  6. Django视图中使用本地缓存

    Django服务器视图使用缓存可以大大减小服务器的压力,对数据实时性要求不高的场景使用缓存非常适合. 使用Django本地缓存 1. 在settings.py配置CACHES CACHES = { ' ...

  7. 后台程序处理 (一)python asyncio 协程使用

    由于脚本需要在完成事件处理后N秒检查事件处理结果,当执行失败时再执行另一个事件处理. 想要最小化完成这个功能.同时在第一时间就将执行完毕的结果反馈给接口. 因此想到使用协程. 使用之前先翻阅了一下现有 ...

  8. python---异步IO(asyncio)协程

    简单了解 在py3中内置了asyncio模块.其编程模型就是一个消息循环. 模块查看: from .base_events import * from .coroutines import * #协程 ...

  9. asyncio协程与并发

    并发编程 Python的并发实现有三种方法. 多线程 多进程 协程(生成器) 基本概念 串行:同时只能执行单个任务 并行:同时执行多个任务 在Python中,虽然严格说来多线程与协程都是串行的,但其效 ...

随机推荐

  1. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  2. Cannot execute request on any known server或DiscoveryClient_UNKNOWN/DESKTOP-MQ8D0C9:8761

    报错信息如下: 2018-08-31 11:45:33.619 WARN 1068 --- [freshExecutor-0] c.n.d.s.t.d.RetryableEurekaHttpClien ...

  3. jquery中的$.fn的用法

    JQuery里的原型prototype分析       http://www.nowamagic.net/librarys/veda/detail/653 jquery中的$.fn的用法       ...

  4. sql 查询 某字段 重复次数 最多的记录

    需求  查询小时气象表中 同一日期.同一城市.同意检测站点  首要污染物出现出书最多的记录 第一步: 添加 排序字段 select StationID,RecordDate,CityID,Primar ...

  5. js中事件冒泡,事件捕获详解

    一.事件流 事件是js与HTML交互的基础,事件流描述的是页面接受事件的顺序,而事件流又分为三个阶段:捕获阶段.目标阶段和冒泡阶段. 如果单纯的事件处理,事件捕获和事件冒泡二选一即可,导致两者并存的原 ...

  6. DevExtreme App 开发记要

        添加插件 除提供的标准插件外,可直接在config.xml中书写配置,然后编译模板,在后台能看到相关的插件了         无法显示百度地图 在IPHONE中正常加载地图,但在安卓中提示BM ...

  7. 【AO笔记】有关使用AO基于shp文件创建网络数据集的一个细节

    前些日子,和群友交流时提及shp文件创建单一网络数据集的创建问题. 由于项目需求,用shp文件创建网络合适,所以不得不去找一些古老的代码资料... 以前的研究中,创建网络数据集是根据IDatasetC ...

  8. JS中如何进行对象的深拷贝

    在JS中,一般的=号传递的都是对象/数组的引用,并没有真正地拷贝一个对象,那如何进行对象的深度拷贝呢?如果你对此也有疑问,这篇文章或许能够帮助到你 一.对象引用.浅层拷贝与深层拷贝的区别 js的对象引 ...

  9. git常用命令总结--廖雪峰老师Git教程命令总结

    学习了廖雪峰老师的Git教程之后的命令总结,重点关于git和远程仓库的东西. 如果没有学过,这是传送门 下面这个图很重要 一.git初始化本地仓库和配置 echo "想输入到文件的内容,一般 ...

  10. Oracle dblink的连接模式的关系测试总结

    这篇主要介绍一下database link由于连接数据库的方式不同遇到的一些问题,我们知道连接ORACLE服务器的模式一般有两种方式:专用服务器连接(dedicated server)和共享服务器连接 ...