协程

协程:

基本概念:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定。总的来说就是能在函数执行过程中挂起,去执行其他异步函数,等挂起条件消失后,再回来执行。await就是 用来声明当前程序挂起,去执行 await 后的异步函数,所以await后只能跟异步函数或有__await__属性的对象。

 

协程的简单实现:

复制代码
def fun1():
    for i in range(3):
        print('fun1中第%s次循环'%i)
        yield

def fun2():
    for j in range(3):
        print('fun2中第%s次循环'%j)
        yield

if __name__ == "__main__":
    f1 = fun1()
    f1.__next__()
    f2 = fun2()
    f2.__next__()
    while True:
        next(f1)
        next(f2)

复制代码

 

 

使用asyncio模块

基本概念:

  • event_loop 事件循环:程序开启一个无限的循环,程序员会把一些函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。
  • coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。
  • task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。基于事件循环创建,loop.create_task(coroutine)
  • future: 代表将来执行或没有执行的任务的结果。它和task上没有本质的区别。基于asyncio.ensure_future(coroutine)创建
  • async/await 关键字:python3.5 用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。

 

复制代码
#最简单的协程
async def fun():        #定义一个协程函数
print('hello')
await asyncio.sleep(1) #使用await挂起,让他去执行其他的协程函数
print('python')
f = fun()
asyncio.run(f)

 

复制代码

 

多任务协程

复制代码

import asyncio
import time
async def func():
print('正在执行func...')
await asyncio.sleep(2)
print('func执行完成')

async def func2():
print('正在执行func2...')
await asyncio.sleep(3)
print('func2执行完成')

start = time.time()
loop = asyncio.get_event_loop() #获取当前的事件循环
tasks = [] #创建一个任务列表

task1 = loop.create_task(func()) #将协程对象封装成一个任务
task2 = loop.create_task(func2())
#task1 = asyncio.ensure_future(func())    #此处也可以用future来代替task
#task2 = asyncio.ensure_future(func2())

tasks.append(task1) #分别将任务加入到任务列表中
tasks.append(task2)

loop.run_until_complete(asyncio.wait(tasks)) #运行事件循环

loop.close() #关闭事件循环
print(time.time() - start)
------注意
asyncio.ensure_future(coroutine) 和 loop.create_task(coroutine)都可以创建一个task,
run_until_complete的参数是一个futrue对象。
当传入一个协程,其内部会自动封装成task,task是Future的子类。isinstance(task, asyncio.Future)将会输出True。
复制代码

 

如果协程函数有返回值。我们可以通过  task.result()来获取返回值

复制代码
import asyncio
import time
async def func():
    start = time.time()
    print('正在执行func...')
    await asyncio.sleep(2)
    print('func执行完成')
    return time.time() - start

async def func2():
    start = time.time()
    print('正在执行func2...')
    await asyncio.sleep(3)
    print('func2执行完成')
    return time.time() - start

loop = asyncio.get_event_loop()     #获取当前的事件循环
tasks = []                          #创建一个任务列表

# task1 = loop.create_task(func())        #将协程对象封装成一个任务
# task2 = loop.create_task(func2())
task1 = asyncio.ensure_future(func())
task2 = asyncio.ensure_future(func2())

tasks.append(task1)                 #分别将任务加入到任务列表中
tasks.append(task2)

loop.run_until_complete(asyncio.wait(tasks))        #运行事件循环
print(task1.result())
print(task2.result())
loop.close()            #关闭事件循环
复制代码

 

协程函数的回调

通过   task1.add_done_callback(call_back)  方法给一份任务绑定相应的回调函数

注意:回调函数call_back(task)的写法,必须携带任务对象作为参数

复制代码
import asyncio
import time
async def func():
    start = time.time()
    print('正在执行func...')
    await asyncio.sleep(2)
    print('func执行完成')
    return time.time() - start

async def func2():
    start = time.time()
    print('正在执行func2...')
    await asyncio.sleep(3)
    print('func2执行完成')
    return time.time() - start

def call_back(task):    #必须要传入task对象
    print('我是func1的回调函数')
    print(task.result())
loop = asyncio.get_event_loop()     #获取当前的事件循环
tasks = []                          #创建一个任务列表

task1 = asyncio.ensure_future(func())
task2 = asyncio.ensure_future(func2())

tasks.append(task1)                 #分别将任务加入到任务列表中
tasks.append(task2)

task1.add_done_callback(call_back)      #给task1绑定相应的回调函数

loop.run_until_complete(asyncio.wait(tasks))        #运行事件循环
print(task1.result())
print(task2.result())
loop.close()            #关闭事件循环

 

 

 
复制代码

 

posted @   powfu  阅读(108)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示