协程asyncio库的学习与理解

基于python文档和一些大佬的博客学习,谈谈我对于协程的学习与理解
协程:coroutine ,简写成:coro

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

协程通过 async/await 语法进行声明

  • 定义函数的时候再头上加一个async就变成了协程
  • 调用的时候也要在函数名前加上await
import asyncio
async def do():
    print('hello')
    await asyncio.sleep(1)
    print('world')
asyncio.run(do())

简单地调用一个协程并不会将其加入执行日程
协程asyncio库的学习与理解_第1张图片

运行 asyncio 程序

asyncio.run(coro, *, debug=False)

  • 执行 coroutine(协程) coro 并返回结果。
  • 如果 debug 为 True,事件循环将以调试模式运行。
  • 此函数总是会创建一个新的事件循环并在结束时关闭之。它应当被用作 asyncio 程序的主入口点,理想情况下应当只被调用一次。

用来运行最高层级的入口点"do()"函数
上面的实例就使用了这个函数

import asyncio
async def do():
    print('hello')
    await asyncio.sleep(1)
    print('world')
asyncio.run(do())

等待

import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print("started at", time.strftime('%X'))

    await say_after(1, 'hello')
    await say_after(2, 'world')

    print("started at", time.strftime('%X'))

asyncio.run(main())

在这里插入图片描述

简单等待

asyncio.wait(aws, *, loop=None, timeout=None, return_when=ALL_COMPLETED)

  • 并发运行 aws 指定的 可等待对象 并阻塞线程直到满足 return_when 指定的条件。
  • 如果 aws 中的某个可等待对象为协程,它将自动作为任务加入日程。
  • 返回两个 Task/Future 集合: (done, pending)。

于是就可以这样调用,实现并发运行

loop.run_until_complete(asyncio.wait(任务单(可为一个列表)))

可等待对象

如果一个对象可以在 await 语句中使用,那么它就是 可等待 对象
有三种主要类型: 协程, 任务Future.

协程

协程属于可等待对象,因此可以在其他协程中被等待:(可用await被调用)

  • 协程函数: 定义形式为 async def 的函数;

  • 协程对象: 调用 协程函数 所返回的对象。

import asyncio

async def nested():
    return 42

async def main():
    nested()
    # 用await调用协程
    print(await nested())
asyncio.run(main())

直接调用nested就报错,说没有用await
第二个用来await声明就可以调用了
协程asyncio库的学习与理解_第2张图片

任务

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

import asyncio
async def nested():
    return 42
async def main():
# 将nested函数用下面的方法打包成一个任务task
# 用await调用任务
    task = asyncio.create_task(nested())
    await task
asyncio.run(main())

Futures

Future 是一种特殊的 低层级 可等待对象,表示一个异步操作的 最终结果
当一个 Future 对象 被等待,这意味着协程将保持等待直到该 Future 对象在其他地方操作完毕。
通常情况下 没有必要 在应用层级的代码中创建 Future 对象。

创建任务

asyncio.create_task(coro)

该函数用来并发运行作为 asyncio 任务多个协程

将 coro 协程 打包为一个 Task 排入日程准备执行。返回 Task 对象。
事件循环
asyncio.get_running_loop()
返回当前 OS 线程中正在运行的事件循环。
如果没有正在运行的事件循环则会引发 RuntimeError。 此函数只能由协程或回调来调用。
该任务会在 get_running_loop() 返回的循环中执行,如果当前线程没有在运行的循环则会引发 RuntimeError。

import asyncio
import time
# 创建一个延迟函数,控制延迟运行
async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)
    
async def main():
    task1 = asyncio.create_task(
        say_after(1, 'hello'))

    task2 = asyncio.create_task(
        say_after(2, 'world'))

    print("started at", time.strftime('%X'))
    # 两个task就像一个代办的任务,然后带着await执行他们
    await task1
    await task2
    print("started at", time.strftime('%X'))
asyncio.run(main())

协程asyncio库的学习与理解_第3张图片
可以发现运行时间和上面写的代码不一样了,就只有我们设置的最长的等待时间:两秒,说明实现了并发运行

休眠

asyncio.sleep(delay, result=None)

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

事件循环

获取时间循环

asyncio.get_running_loop()
返回当前 OS 线程中正在运行的事件循环,如果没有正在运行的事件循环则会引发 RuntimeError。

asyncio.get_event_loop()
获取当前事件循环, 如果当前 OS 线程没有设置当前事件循环并且 set_event_loop() 还没有被调用,asyncio 将创建一个新的事件循环并将其设置为当前循环

asyncio.set_event_loop(loop)
将 loop 设置为当前 OS 线程的当前事件循环

asyncio.new_event_loop()
创建一个新的事件循环

运行和停止

loop.run_until_complete(future)
运行直到 future ( Future 的实例 ) 被完成
如果参数是 coroutine object(协程) ,将被隐式调度为 asyncio.Task 来运行

loop.run_forever()
运行事件循环直到 stop() 被调用

loop.stop()
停止事件循环

学到这里,就有能力看懂小泽的这段代码了

import asyncio
import time

async def english():
    print('小明正在学英语...')
    await asyncio.sleep(2)
    print('小明已经学了两秒英语...')

async def math():
    print('小明正在学数学...')
    await asyncio.sleep(2)
    print('小明已经学了两秒数学...')

async def zhexue():
    print('小明正在学哲学...')
    await asyncio.sleep(4)
    print('小明已经学了四秒哲学...')

if __name__ == '__main__':
    start = time.time()
    # 建立任务库
    renwu = [english(),math(),zhexue()]
    # 初始化地盘
    dipan = asyncio.get_event_loop()
    # 放置任务
    dipan.run_until_complete(asyncio.wait(renwu))
	# 结束计时
    end = time.time()
    print('小明学完所有课程啦!总用时:'+str(end-start)+'秒!')

你可能感兴趣的:(笔记,python,python,多线程)