Django如何使用asyncio协程和ThreadPoolExecutor多线程

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)实现协程
    """
    self.id = 5
    start_time = time.time()

    '''
    # 同步执行
    # results = [self.io_task1(self.id),
    # self.io_task2(self.id),
    # self.io_task2(self.id)]
    '''

    loop = asyncio.new_event_loop() # 或 loop = asyncio.SelectorEventLoop()
    asyncio.set_event_loop(loop)
    self.loop = loop

    works = [
      asyncio.ensure_future(self.io_task3(5)),
      asyncio.ensure_future(self.io_task3(5)),
      asyncio.ensure_future(self.io_task3(5)),
      asyncio.ensure_future(self.io_task3(5)),
      asyncio.ensure_future(self.io_task3(5)),

    ]

    try:

      results = loop.run_until_complete(asyncio.gather(*works)) # 两种写法
      # 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):

    tasks = (
      self.make_future(self.io_task1, self.id),
      self.make_future(self.io_task2, self.id),
      self.make_future(self.io_task2, self.id),
      self.make_future(self.io_task1, self.id),
      self.make_future(self.io_task2, self.id),
      self.make_future(self.io_task2, self.id),
    )
    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

  def io_task1(self, sleep_time):
    time.sleep(sleep_time)
    return 66

  def io_task2(self, sleep_time):
    time.sleep(sleep_time)
    return 77

  async def io_task3(self, sleep_time):
    # await asyncio.sleep(sleep_time)
    s = await self.do(sleep_time)
    return s

  async def do(self, sleep_time):
    await asyncio.sleep(sleep_time)
    return 66

在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, self.io_task2, self.io_task1, self.io_task2, self.io_task2)
    with ThreadPoolExecutor(len(tasks)) as executor:
      for task in tasks:
        future = executor.submit(task, 5)
        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):

    results = []
    for future in future_set:
      results.append(future.result())
    return results

  def io_task1(self, sleep_time):
    time.sleep(sleep_time)
    return 66

  def io_task2(self, sleep_time):
    time.sleep(sleep_time)
    return 77

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解pycharm的newproject左侧没有出现项目选项的情况下创建Django项目的解决方法/社区版pycharm创建django项目的方法

    首先,我当时出现的问题是newproject创建的时候没有django的选项,查了半天发现我安装的pycharm是社区版本.所以需要用终端命令行的方式创建django项目. 首先,随便打开一个项目,然后在pycharm界面的左下角有Terminal终端的图标,点开. cd返回根目录 在终端输入你PycharmProjects的目录,由于我是mac 端,我输入的是:cd /Users/apple/PycharmProjects 进入目录后,输入:django-admin startproject

  • 在Django的View中使用asyncio的方法

    起步 Django 是个同步框架,本文并不是 让 Django 变成异步框架.而是对于在一个 view 中需要请求多次 http api 的场景. 一个简单的例子 例子来源于 https://stackoverflow.com/questions/44667242/python-asyncio-in-django-view : def djangoview(request, language1, language2): async def main(language1, language2):

  • 详解多线程Django程序耗尽数据库连接的问题

    Django的ORM是非常好用的,哪怕不是做Web项目也值得一用,所以网上也可以找到不少使用 Django 开发非Web项目的资料,因为除了ORM之个,命令行.配置文件等组件也非常好用. 最近用这种方式开发了一个非Web项目,而且是多线程的.有N个工作线程从DB中获取jobs,并把结果写回DB.简单来说就是这样. 项目运行一段时间后,发现数据库连接耗尽了,幸好内存大,然后一直往上调,最后连接数都上九千多一万了.耗尽连接数的时候,PostgreSQL 会出现类似这样的错误: FATAL: rema

  • python自动化测试三部曲之request+django实现接口测试

    国庆期间准备写三篇博客,介绍和总结下接口测试,由于国庆期间带娃,没有按照计划完成,今天才完成第二篇,惭愧惭愧. 这里我第一篇博客的地址:https://www.jb51.net/article/197004.htm,主要是介绍unittest框架,有兴趣的同学们可以移步去查阅 这里废话少说,进入正题 我的思路是这样的 1.先用django实现登陆.增加.删除.查看4个接口 2.在excel定义好测试案例.然后读取excel中的案例,然后把案例用unittest框架组装和封装 3.启动django

  • 记一次Django响应超慢的解决过程

    在本地windows机器开发的Django项目运行正常,放到服务器上后响应超慢,花了一整个工作日没找到原因(非常绝望),又花了一整个周末才找到原因和临时解决办法,如果你的项目超慢可以参考一下解决思路. 排查过程: 1.怀疑是Python环境问题,到服务器上各种虚拟环境版本进行尝试,无果. 2.因为用了mysql数据库,开始用pymysql包连接改动了一些参数,担心是驱动问题导致数据库查的慢,更换mysqlclient包后,响应依旧慢. 3.担心是有什么报错导致慢,于是艰难地开启了debug模式(

  • Django连接本地mysql数据库(pycharm)的步骤

    第一步:更改setting.py中的DATABASES # 配置数据库 DATABASES = { 'default': { # python自带的一个数据库,基本不会被使用 # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # 注册我们自己使用的数据库连接 'ENGINE': 'django.db.backends.mysql', # 数据库引擎 'NAME': '

  • Django实现文章详情页面跳转代码实例

    1.由于不支持博客首页到文章详情页的跳转,只能打开第一篇文章的详情页 2.所以需要做以下工作: 设计文章详情页的url,完善视图函数逻辑,实现首页跳转 /blog/detail =>不能指定某一篇文章 /blog/detail/1 => 博客唯一id唯1的文章 /blog/detail/2 => 博客唯一id唯2的文章 /blog/detail/3 => 博客唯一id唯3的文章 /blog/detail/...... 获取URL路径参数:<> 页面跳转:href指定ht

  • Django生成数据库及添加用户报错解决方案

    Django生成数据库表时报错 __init__() missing 1 required positional argument: 'on_delete' 原因: 在django2.0后,定义外键和一对一关系的时候需要加上on_delete选项,此参数为了避免两个表里的数据不一致问题,不然会报错 例如: owner=models.ForeignKey(UserProfile)--->报错 owner=models.ForeignKey(UserProfile,on_delete=models.

  • Django如何使用asyncio协程和ThreadPoolExecutor多线程

    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在主线程中调用一次,它将自动创建一个循环对象并将其设

  • python asyncio 协程库的使用

    asyncio 是 python 力推多年的携程库,与其 线程库 相得益彰,更轻量,并且协程可以访问同一进程中的变量,不需要进程间通信来传递数据,所以使用起来非常顺手. asyncio 官方文档写的非常简练和有效,半小时内可以学习和测试完,下面为我的一段 HelloWrold,感觉可以更快速的帮你认识 协程 . 定义协程 import asyncio import time async def say_after(delay, what): await asyncio.sleep(delay)

  • python Task在协程调用实例讲解

    1.说明 Tasks用于并发调度协程,通过asyncio.create_task(协程对象)创建Task对象,使协程能够加入事件循环,等待调度执行.除使用asyncio.create_task()函数外,还可使用低级loop.create_task()或ensure_future()函数.推荐使用手动实例Task对象. 2.使用注意 Python3.7中添加到asyncio.create_task函数.在Python3.7之前,可以使用低级asyncio.ensure_future函数. 3.实

  • python实习总结(yeild,async,azwait和协程)

    目录 一.yield使用简析 二.async和await的使用 1.什么是进程.协程.异步? 2.如何处理200W数量的url,把所有的url保存下来? 3.使用async的await和gather 三.协程的理解 总结 一.yield使用简析 yield是一个生成器generator,返回一个interable对象. 该对象具有next()方法,可以通过next()查看接下来的元素是什么. 1.interable对象 ,可以遍历的对象,如: list,str,tuple,dict,file,x

  • 详解php协程知识点

    多任务 (并行和并发) 在讲协程之前,先谈谈多进程.多线程.并行和并发. 对于单核处理器,多进程实现多任务的原理是让操作系统给一个任务每次分配一定的 CPU 时间片,然后中断.让下一个任务执行一定的时间片接着再中断并继续执行下一个,如此反复. 由于切换执行任务的速度非常快,给外部用户的感受就是多个任务的执行是同时进行的. 多进程的调度是由操作系统来实现的,进程自身不能控制自己何时被调度,也就是说: 进程的调度是由外层调度器抢占式实现的 而协程要求当前正在运行的任务自动把控制权回传给调度器,这样就

  • 深入理解 Java、Kotlin、Go 的线程和协程

    前言 Go 语言比 Java 语言性能优越的一个原因,就是轻量级线程Goroutines(协程Coroutine).本篇文章深入分析下 Java 的线程和 Go 的协程. 协程是什么 协程并不是 Go 提出来的新概念,其他的一些编程语言,例如:Go.Python 等都可以在语言层面上实现协程,甚至是 Java,也可以通过使用扩展库来间接地支持协程. 当在网上搜索协程时,我们会看到: Kotlin 官方文档说「本质上,协程是轻量级的线程」. 很多博客提到「不需要从用户态切换到内核态」.「是协作式的

  • 基于asyncio 异步协程框架实现收集B站直播弹幕

    前言 虽然标题是全站,但目前只做了等级 top 100 直播间的全天弹幕收集. 弹幕收集系统基于之前的B 站直播弹幕姬 Python 版修改而来.具体协议分析可以看上一篇文章. 直播弹幕协议是直接基于 TCP 协议,所以如果 B 站对类似我这种行为做反制措施,比较困难.应该有我不知道的技术手段来检测类似我这种恶意行为. 我试过同时连接 100 个房间,和连接单个房间 100 次的实验,都没有问题.>150 会被关闭链接. 直播间的选取 现在弹幕收集系统在选取直播间上比较简单,直接选取了等级 to

  • python 使用事件对象asyncio.Event来同步协程的操作

    事件对象asyncio.Event是基于threading.Event来实现的. 事件可以一个信号触发多个协程同步工作, 例子如下: import asyncio import functools def set_event(event): print('setting event in callback') event.set() async def coro1(event): print('coro1 waiting for event') await event.wait() print(

  • Python协程asyncio模块的演变及高级用法

    Python协程及asyncio基础知识 协程(coroutine)也叫微线程,是实现多任务的另一种方式,是比线程更小的执行单元,一般运行在单进程和单线程上.因为它自带CPU的上下文,它可以通过简单的事件循环切换任务,比进程和线程的切换效率更高,这是因为进程和线程的切换由操作系统进行. Python实现协程的主要借助于两个库:asyncio和gevent.由于asyncio已经成为python的标准库了无需pip安装即可使用,这意味着asyncio作为Python原生的协程实现方式会更加流行.本

  • 浅谈Python协程asyncio

    一.协程 官方描述; 协程是子例程的更一般形式. 子例程可以在某一点进入并在另一点退出. 协程则可以在许多不同的点上进入.退出和恢复. 它们可通过 async def 语句来实现. 参见 PEP 492. 协程不是计算机内部提供的,不像进程.线程,由电脑本身提供,它是由程序员人为创造的, 实现函数异步执行. 协程(Coroutine),也可以被称为微线程,是一种用户太内的上下文切换技术,其实就是通过一个线程实现代码块相互切换执行.看上去像子程序,但执行过程中,在子程序内部可中断,然后转而执行别的

随机推荐