2020.7.8 asyncio.Future

发布于 2020-07-08  86 次阅读


Table of Contents

  • 1.导入 from django.db import transaction
  • 2.装饰器 @transaction.atomic 装饰函数,
    • 整个函数都在事务中,所以不是很灵活(比如有的数据需要插入)
  • with语句用法
    • 1.导入 from django.db import transaction
    • 2.with transaction.atomic():
      • 创建保存点
        • save_id = transaction.savepoint()
      • 回滚到保存点
        • transaction.savepoint_rollback(save_id)
      • 提交从保存点到当前状态的所有数据库事务操作
        • transaction.savepoint_commit(save_id)
  • 三个方法实现事务
    • 创建保存点
      • save_id = transaction.savepoint()
    • 回滚到保存点
      • transaction.savepoint_rollback(save_id)
    • 提交从保存点到当前状态的所有数据库事务操作
      • transaction.savepoint_commit(save_id)
  • 处理数据库数据问题=数据库的锁

    • 悲观锁
    • 乐观锁
    • celery任务队列
  • Python asyncio.Future对象 课程

    • asyncio.Future对象

      • task的基类,task继承Future对象,task对象内部await基于Future对象
      • 有一个属性_state 可以判断状态 finish
      • async def main():
          # 获取事件循环
          loop = asyncio.get_running_loop()
          # 创建一个任务,
          fut = loop.create_future()
          # 死循环停住
          await fut
        asyncio.run(main())
        
        async def set_after(fut):
          await asyncio.sleep(2)
          fut.set_result("666")
        async def main():
          loop = asyncio.get_running_loop()
          fut = loop.create_future()
          await loop.create_task(set_after(fut))
        asyncio.run(main())

    • 重点知识

      • async 早期的装饰器(@asyncio.coroutine)

        • 标志当前函数是一个协程函数
        • 协程函数() 返回一个协程对象,并不执行
      • await 早期的yield from

        • 暂停协程,告诉协程先去执行别的协程,
        • 执行完毕,或者遇到阻塞会切换回函数
        • 可以使用在:协程对象,Task对象,Future对象
      • asyncio.wait()

        • 作用:执行多个协程,自动切换
        • 参数:可迭代对象,如果是协程对象,
        • 自动创建task(ensure_future()方法)
      • asycnio.create_task(coro)

        • 接收参数是一个协程对象,
        • 创建可以实现异步执行任务
        • 其他方法(非python37)
          • loop.create_task()
          • ensure_future()
      • asyncio.run() python3.7

        • 开始执行协程函数
        • 非python3.7执行
          • loop = asyncio.get_event_loop()
            • 创建一个事件循环
          • loop.run_until_complete(result)
            • 将协程当做任务提交到事件循环的任务列表中,协程执行完成之后终止。
        • asyncio.run 本质上就是上面两个步骤
      • asyncio.get_running_loop()

        • 获取当前的事件循环
    • asyncio.Future对象

      • 是task的基类,更加的底层抽象,一般不会使用
      • 1.创建方法:
        • 获取 loop = asyncio.get_running_loop()
        • 创建 fut = loop.create_future()
        • await fut # 空的Future 死循环
      • 2.发送一个数据
        • import asyncio
          async def set_after(fut):
              await asyncio.sleep(2)
              fut.set_result("666")
          async def main():
              # 获取当前事件循环
              loop = asyncio.get_running_loop()
              # 创建一个任务(Future对象),没绑定任何行为,则这个任务永远不知道什么时候结束。
              fut = loop.create_future()
              # 创建一个任务(Task对象),绑定了set_after函数,函数内部在2s之后,会给fut赋值。
              # 即手动设置future任务的最终结果,那么fut就可以结束了。
              await loop.create_task(set_after(fut))
              # 等待 Future对象获取 最终结果,否则一直等下去
              data = await fut
              print(data)
          asyncio.run(main())

      • futures.Future

        • 这个对象是基于线程池和进程池实现异步操作时使用的对象。
        • 可以和asyncio的Future结合使用,第三方模块不支持协程时候使用
        • 常用方法
          • cancel(): 取消future的执行,调度回调函数
          • result(): 返回future代表的结果
          • exception(): 返回future中的Exception
          • add_done_callback(fn): 添加一个回调函数,当future执行的时候会调用这个回调函数
          • remove_done_callback(fn): 从“call whten done”列表中移除所有callback的实例
          • set_result(result): 将future标为执行完成,并且设置result的值
          • set_exception(exception): 将future标为执行完成,并设置Exception
        • import time
          from concurrent.futures import Future
          from concurrent.futures.thread import ThreadPoolExecutor
          from concurrent.futures.process import ProcessPoolExecutor
          def func(value):
              time.sleep(1)
              print(value)
          pool = ThreadPoolExecutor(max_workers=5) # 线程池
          
          # 或 pool = ProcessPoolExecutor(max_workers=5) # 进程池
          
          for i in range(10):
              fut = pool.submit(func, i)
              print(fut)

        • 结合使用
          • import time
            import asyncio
            import concurrent.futures
            def func1():
                # 某个耗时操作
                time.sleep(2)
                return "string"
            async def main():
                loop = asyncio.get_running_loop()
                # 1. Run in the default loop's executor ( 默认ThreadPoolExecutor )
                # 第一步:内部会先调用 ThreadPoolExecutor 的 submit 方法去线程池中申请一个线程去执行func1函数,并返回一个concurrent.futures.Future对象
                # 第二步:调用asyncio.wrap_future将concurrent.futures.Future对象包装为asycio.Future对象。
                # 因为concurrent.futures.Future对象不支持await语法,所以需要包装为 asycio.Future对象 才能使用。
                fut = loop.run_in_executor(None, func1)
                result = await fut
                print('default thread pool', result)
                # 2. Run in a custom thread pool:
                # with concurrent.futures.ThreadPoolExecutor() as pool:
                #     result = await loop.run_in_executor(
                #         pool, func1)
                #     print('custom thread pool', result)
                # 3. Run in a custom process pool:
                # with concurrent.futures.ProcessPoolExecutor() as pool:
                #     result = await loop.run_in_executor(
                #         pool, func1)
                #     print('custom process pool', result)
            asyncio.run(main())

      • Future处理并发

        • Future实例表示可能完成或者未完成的延时计算
        • 与Twisted中的Deferred类、Tornado框架中的Future类的功能类似
        • 两者之间的不同:
          • 1.concurrent.futures.Future 不支持await
          • 2.asyncio.Future.result() 和asyncio.Future.exception() 不支持timeout
          • 3.asyncio.Future.result() 和 asyncio.Future.exception() InvalidStateError 未完成的异常
          • 4.asyncio.Future.add_done_callback() 不是立即执行,只是在loop.call_soon()中插入
          • 5.asyncio Future 不兼容 concurrent.futures.wait()和as_completed()函数
          • 6.python 用asyncio.wrap_future() 可以将futures.Future包装成asyncio.Future对象函数
  • 4.扩展延伸知识

    5.知识内容个人梳理

    6.今天都复习了之前的什么内容