python中await async_python---await/async关键字

首先看正常的两个函数之间的执行

def func1():

print("func1 start")

print("func1 end")

def func2():

print("func2 start")

print("func2 a")

print("func2 b")

print("func2 c")

print("func2 end")

func1()

func2()

func1 start

func1 end

func2 start

func2 a

func2 b

func2 c

func2 end

无法实现两个函数之间的交互。

将这两个函数设置为协程,加上async关键字

asyncdef func1():

print("func1 start")

print("func1 end")asyncdef func2():

print("func2 start")

print("func2 a")

print("func2 b")

print("func2 c")

print("func2 end")

f1=func1()

f2=func2()

print(f1,f2)

sys:1: RuntimeWarning: coroutine 'func1'was never awaited  #警告信息

sys:1: RuntimeWarning: coroutine 'func2' was never awaited

#上面不再只是函数,而变为协程对象,协程在调用时,不会被执行

那么,为什么要有一个协程对象?代码到底如何执行?

关键之处是协程确实是与 Python 的生成器非常相似,也都有一个 send 方法。我们可以通过调用 send 方法来启动一个协程的执行。

f1 =func1()

f2=func2()try:

print('f1.send')

f1.send(None)

except StopIterationase:  #这里也是需要去捕获StopIteration方法

passtry:

print('f1.send')

f2.send(None)

except StopIterationase:

pass

StopIteration 异常是一种标记生成器(或者像这里的协程)执行结束的机制。虽然这是一个异常,但是确实是我们期望的!我们可以用适当的 try-catch 代码将其包起来,这样就可以避免错误提示。

上面虽然将两个协程都执行起来了,但是并没有做到交替执行,和最初的并无不同,而且似乎更加麻烦

协程与线程相似的地方是多个线程之间也可以交替执行,不过与线程不同之处在于协程之间的切换是显式的,而线程是隐式的(大多数情况下是更好的方式)。所以我们需要加入显式切换的代码。

我们可能根据生成器或者协程gevent的使用,而去推测这种方案:(是错误的)

asyncdef func1():

print("func1 start")yieldprint("func1 end")

不允许在本地协程函数中使用yield,但是作为替换,我们可以使用到await 表达式来暂停协程的执行。注意await _something_,这里的_something_代表的是基于生成器的协程对象,或者一个特殊的类似 Future的对象。

下面使用一个基于生成器的协程函数

import types

@types.coroutine

defswitch():yield

asyncdef func1():

print("func1 start")await switch()

print("func1 end")asyncdef func2():

print("func2 start")

print("func2 a")

print("func2 b")

print("func2 c")

print("func2 end")

f1=func1()

f2=func2()try:

f1.send(None)

except StopIterationase:

passtry:

f2.send(None)

except StopIterationase:

pass

func1 start

func2 start

func2 a

func2 b

func2 c

func2 end

注意上面的输出:只是执行了函数的转换,有func1转换到func2,并没有再回到func1中。那么如何让其在回到func1中呢。

我们可以基于生成器一样再次对func1协程使用send方法,再次激活yield向下执行

import types

@types.coroutine

defswitch():yield

asyncdef func1():

print("func1 start")await switch()

print("func1 end")asyncdef func2():

print("func2 start")

print("func2 a")

print("func2 b")

print("func2 c")

print("func2 end")

f1=func1()

f2=func2()try:

f1.send(None)

except StopIterationase:

passtry:

f2.send(None)

except StopIterationase:

passtry:

f1.send(None)

except StopIterationase:

pass

func1 start

func2 start

func2 a

func2 b

func2 c

func2 end

func1 end

上面可以实现两个函数交替一次,回到原协程中。但是我们更加希望连续不断的调用send驱动不同的协程去执行,直到send抛出 StopIteration 异常。

为此我们

新建一个函数,这个函数传入一个协程列表,函数执行这些协程直到全部结束。我们现在要做的就是调用这个函数。

import types

@types.coroutine

defswitch():yield

asyncdef func1():

print("func1 start")await switch()

print("func1 e")await switch()

print("func1 end")asyncdef func2():

print("func2 start")

print("func2 a")await switch()

print("func2 b")

print("func2 c")await switch()

print("func2 end")

def run(task_list):

coro_list=list(task_list)whilecoro_list:for coro inlist(coro_list):try:

coro.send(None)

except StopIteration:

coro_list.remove(coro)

f1=func1()

f2= func2()

run([f1,f2])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值