python 异步库 asyncio

分类: Python

2020-11-25

|

401

|

评论:0

分享:

asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。

官方文档(python3.8+): https://docs.python.org/zh-cn/3.8/library/asyncio-task.html

//ps:asyncio库各个python版本差异比较大,在3.7-3.9和3.4-3.6有较大的风格差异,本文章源码运行环境默认为x86-64的python3.8.若存在其他版本的代码,会先表明py版本。

test1 创建异步任务,并行执行异步任务

import asyncio
from time import time


async def say_latter(delay, words):
    await asyncio.sleep(delay)
    print(words, end="")


async def main():
    print("start time: {}".format(time()))
    task1 = asyncio.create_task(
        say_latter(1, "hello")
    )

    task2 = task1 = asyncio.create_task(
        say_latter(10, " world\n")
    )

    await task1
    await task2

    print("end time: {}".format(time()))

asyncio.run(main())

运行结果

start time: 1606293382.8778462
hello world
end time: 1606293392.8871644

可等待对象

如果一个对象可以在 await 语句中使用,那么它就是 可等待 对象。许多 asyncio API 都被设计为接受可等待对象。

可等待 对象有三种主要类型: 协程, 任务Future.

协程

Python 协程属于 可等待 对象,因此可以在其他协程中被等待。

文档中 "协程" 可用来表示两个紧密关联的概念:

  • 协程函数: 定义形式为 async def 的函数;
  • 协程对象: 调用 协程函数 所返回的对象。

asyncio 也支持旧式的 基于生成器的 协程(3.4-3.6版本中使用这种方式的协程,具体可见官方文档)。

任务

任务 被用来设置日程以便 并发 执行协程。

当一个协程通过 asyncio.create_task() 等函数被打包为一个 任务,该协程将自动排入日程准备立即运行。

Futures

Future 是一种特殊的 低层级 可等待对象,表示一个异步操作的 最终结果

当一个 Future 对象 被等待,这意味着协程将保持等待直到该 Future 对象在其他地方操作完毕。

在 asyncio 中需要 Future 对象以便允许通过 async/await 使用基于回调的代码。

通常情况下 没有必要 在应用层级的代码中创建 Future 对象。

Future 对象有时会由库和某些 asyncio API 暴露给用户,用作可等待对象。


运行 asyncio 程序

asyncio.run(coro, *, debug=False)【3.7新增特性】

执行 coroutine coro 并返回结果。

此函数运行传入的协程,负责管理 asyncio 事件循环并 完结异步生成器。当有其他 asyncio 事件循环在同一线程中运行时,此函数不能被调用。如果 debugTrue,事件循环将以调试模式运行。此函数总是会创建一个新的事件循环并在结束时关闭之。它应当被用作 asyncio 程序的主入口点,理想情况下应当只被调用一次。

//asyncio.run() 的源代码可以在 Lib/asyncio/runners.py 中找到。


创建任务

asyncio.create_task(coro, *, name=None)【3.7新特性】

coro 协程 打包为一个 Task 排入日程准备执行。返回 Task 对象。name 不为 None,它将使用 Task.set_name() 来设为任务的名称。该任务会在 get_running_loop() 返回的循环中执行,如果当前线程没有在运行的循环则会引发 RuntimeError。此函数 在 Python 3.7 中被加入。在 Python 3.7 之前,可以改用低层级的 asyncio.ensure_future() 函数。

休眠

coroutine asyncio.sleep(delay, result=None, *, loop=None)

阻塞 delay 指定的秒数。如果指定了 result,则当协程完成时将其返回给调用者。sleep() 总是会挂起当前任务,以允许其他任务运行.

Deprecated since version 3.8, will be removed in version 3.10: loop 形参

并发运行任务

awaitable asyncio.gather(*aws, loop=None, return_exceptions=False)

并发 运行 aws 序列中的 可等待对象

如果 aws 中的某个可等待对象为协程,它将自动作为一个任务加入日程。

如果所有可等待对象都成功完成,结果将是一个由所有返回值聚合而成的列表。结果值的顺序与 aws 中可等待对象的顺序一致。

如果 return_exceptionsFalse (默认),所引发的首个异常会立即传播给等待 gather() 的任务。aws 序列中的其他可等待对象 不会被取消 并将继续运行。如果 return_exceptionsTrue,异常会和成功的结果一样处理,并聚合至结果列表。如果 gather() 被取消,所有被提交 (尚未完成) 的可等待对象也会 被取消。如果 aws 序列中的任一 Task 或 Future 对象 被取消,它将被当作引发了 CancelledError 一样处理 -- 在此情况下 gather() 调用 不会 被取消。这是为了防止一个已提交的 Task/Future 被取消导致其他 Tasks/Future 也被取消。

Deprecated since version 3.8, will be removed in version 3.10: loop 形参。

基于生成器的协程

//对基于生成器的协程的支持 已弃用 并计划在 Python 3.10 中移除。基于生成器的协程是 async/await 语法的前身。它们是使用 yield from 语句创建的 Python 生成器,可以等待 Future 和其他协程。基于生成器的协程应该使用 @asyncio.coroutine 装饰,虽然这并非强制。

@asyncio.coroutine

用来标记基于生成器的协程的装饰器。此装饰器使得旧式的基于生成器的协程能与 async/await 代码相兼容:

@asyncio.coroutine
def old_style_coroutine():
    yield from asyncio.sleep(1)

async def main():
    await old_style_coroutine()

此装饰器不应该被用于 async def 协程。Deprecated since version 3.8, will be removed in version 3.10: 请改用 async def。

asyncio.iscoroutine(obj)

此方法不同于 inspect.iscoroutine() 因为它对基于生成器的协程返回 True。

asyncio.iscoroutinefunction(func)

如果 func 是一个 协程函数 则返回 True。

此方法不同于 inspect.iscoroutinefunction() 因为它对以 @coroutine 装饰的基于生成器的协程函数返回 True.

Powered by Froala Editor



转载请注明来源

文章:python 异步库 asyncio

链接:/article/23

作者:大猫

标签: 异步
本文共 0 个回复

发表评论 (对文章评论)

captcha