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. Java〜slf4日志框架的使用

    slf4日志可以支持注解的方式开启它,然后在使用时直接使用占位符,而不需要手动拼接字符串,这点在性能上也做到了最好. 一 build.gradle依赖项 compileOnly('org.projec ...

  2. java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)

    目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...

  3. Springboot 系列(八)动态Banner与图片转字符图案的手动实现

    使用过 Springboot 的对上面这个图案肯定不会陌生,Springboot 启动的同时会打印上面的图案,并带有版本号.查看官方文档可以找到关于 banner 的描述 The banner tha ...

  4. webstorm 2018.2.3 license server

    推荐地址:http://idea.lanyus.com/ 使用前请将“0.0.0.0 account.jetbrains.com”添加到hosts文件中

  5. 总结安装webpack过程中遇到的错误及解决方案

    1.安装不成功的报错: 解决方案:清除缓存 2.打包不成功: 解决方案:填写打包路径时的“__dirname”有两个下划线 3.打包报错: 解决方案:正确填写路径为“./style.css”

  6. arcgis api 4.x for js之基础地图篇

    arcgis api3.x for js转向arcgis api4.x,我也是最近的3-4个月时间的事情,刚好公司有个webgis项目需要展示三维场景,项目选择arcgis api4.x.我纯碎记录一 ...

  7. 使用AndroidStudio编写APICloud模块需要注意的地方,解决模块未定义。

    在新的版本下,使用AndroidStudio编写APICloud模块,已经非常简单了,解决模块未定义,最重要的就是要先看官方的视频! 注意在模块的module.json中name很重要,建议做到三统一 ...

  8. Java中的守护线程

    守护线程的概念 在java中有两种线程,守护线程和非守护线程,其两者并没有本质的区别,唯一的区别就是当前的用户线程退出的时候,若只存在唯一的A线程,若A线程为守护线程,那么JVM将会直接退出,否则JV ...

  9. 简单的C#实体映射 AutoMapper

    AutoMapper是对象到对象的映射工具.在完成映射规则之后,AutoMapper可以将源对象转换为目标对象. 要映射实体 public class SourceModel { public int ...

  10. EOS开发入门

    EOS开发入门   在上一篇文章<EOS开发环境搭建>中,我们已经完成了EOS开发环境的搭建,本次为大家带来的是EOS开发入门的相关内容. 1. EOS的合约开发基础   智能合约是一种旨 ...