首页 > 其他分享 >协程

协程

时间:2022-11-18 22:57:04浏览次数:37  
标签:task 协程 time print loop asyncio

协程:

基本概念:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定。总的来说就是能在函数执行过程中挂起,去执行其他异步函数,等挂起条件消失后,再回来执行。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()            #关闭事件循环

 


 

 

 

标签:task,协程,time,print,loop,asyncio
From: https://www.cnblogs.com/powfu/p/16905176.html

相关文章

  • 简易血槽残影设计方案(使用协程)
    今天看了段DNF视频,有发现到血条变化效果是这样的:  这里为了突出Boss受到的伤害之大,也就是玩家的伤害之高,以至于Boss的血条变化会出现残影效果。那么,就简......
  • python 多进程 多线程 协程
    多进程-进程池1fromconcurrent.futuresimportProcessPoolExecutor23withProcessPoolExecutor(max_workers=10)asexecutor:4results=executor.map......
  • Python用yield form 实现异步协程爬虫
    很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习。争取用看得懂的字来描述问题。1.什么是yield如果还没有怎么用过的话,直接把yield......
  • Python3-异步协程
     importasyncioimporttimeasyncdefget_request(url):print('正在请求的url:',url)awaitasyncio.sleep(2)#支持异步模块代码print('请求结束:'......
  • 线程、 进程、 协程
    1.多线程(单线程、多线程)#线程、进程#线程是执行单位进程->公司线程->员工#进程是资源单位(每一个进程里面至少有一个线程)#单线程deffunc():for......
  • Unity之"诡异"的协程
    为什么说是诡异的协程呢?首先从一个案例说起吧,示例如下:游戏目标:让小车进入到对应颜色屋子里,即可获得一分。(转弯的道路可控) 为了让小车能够平滑转弯,小车的前进方向需要......
  • 协程
    概念提示 协程不是进程也不是线程,而是一个特殊的函数。这个函数可以在某个地方被“挂起”,并且可以重新在挂起处外继续运行。所以说,协程与进程、线程相比并不是一个维度......
  • 【Go】协程
    今天主要学习了一下go语言的多线程,也写了一些例子,最开始还是很困惑。比如下面这个例子:packagemainimport"fmt"funcloop(){fori:=0;i<10;i++{fmt.Printf("......
  • 协程 + epoll 的两个小例子
    getcontext/setupcontext/swapcontext/setcontext 方式的协程实现#include<stdio.h>#include<stdlib.h>#include<string.h>#include<poll.h>#include<errno.h>......
  • lua协程
    localcoroutine=coroutinelocaltable=tablelocalcoroutine_create=coroutine.createlocalcoroutine_resume=coroutine.resumelocalcoroutine_yield=co......