• 如何在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
    

      

     

  • 相关阅读:
    Sql语句创建表
    刷新、关闭等误操作造成当前页面信息的丢失的解决方案
    asp.net文本框中只允许用户输入数字
    为每个用户创建文件夹,并实现图片上传
    在updatepanel中使用fileupload控件
    解决弹出提示框后字体变大的BUG
    SQL 2005新增的几个函数之学习
    .net实现单张图片的上传
    数据分页
    所谓三门问题
  • 原文地址:https://www.cnblogs.com/feifeifeisir/p/13723054.html
Copyright © 2020-2023  润新知