基于python文档和一些大佬的博客学习,谈谈我对于协程的学习与理解
协程:coroutine ,简写成:coro
async
就变成了协程await
import asyncio
async def do():
print('hello')
await asyncio.sleep(1)
print('world')
asyncio.run(do())
asyncio.run(coro, *, debug=False)
用来运行最高层级的入口点"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)
于是就可以这样调用,实现并发运行
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.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())
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.sleep(delay, result=None)
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)+'秒!')