标签:委托 完成 pytho sync 发送消息 进程 参数 python 专注
??协程(Coroutine),又称微线程,纤程。通常我们认为线程是轻量级的进程,因此我们也把协程理解为轻量级的线程即微线程。
??协程的作用是在执行函数A时可以随时中断去执行函数B,然后中断函数B继续执行函数A(可以自由切换)。这里的中断,不是函数的调用,而是有点类似CPU的中断。这一整个过程看似像多线程,然而协程只有一个线程执行。
例:
def simple_coroutine():
print('-> start')
x = yield
print(x)
print('-> end')
#主线程
sc = simple_coroutine()
# 可以使用sc.send(None),效果一样
next(sc) #预激
sc.send('go')
执行结果如下:
-> start
go
-> end
抛出StopIteration
simple_coroutine()
是一个生成器,由next(sc)
预激,启动协程,执行到第一个yield中断send()
方法给yield传入参数,继续执行
GEN_CLOSED:执行结束
终止协程的一种方式:发送某个哨符值,让协程退出。内置的 None 和Ellipsis 等常量经常用作哨符值
??asyncio
是Python3.4版本引入的标准库,直接内置了对异步IO的支持。asyncio
的异步操作,需要在coroutine
中通过yield from
完成。
例:
import asyncio
@asyncio.coroutine
def test(i):
print('test_1', i)
r = yield from asyncio.sleep(1)
print('test_2', i)
loop = asyncio.get_event_loop()
tasks = [test(i) for i in range(1,3)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
@asyncio.coroutine
把一个generator
标记为coroutine
类型,然后就把这个coroutine
扔到EventLoop
中执行。test()
会首先打印出test_1yield from
语法可以让我们方便地调用另一个generator
。由于asyncio.sleep()
也是一个coroutine
,所以线程不会等待asyncio.sleep()
,而是直接中断并执行下一个消息循环。asyncio.sleep()
返回时,线程就可以从yield from
拿到返回值(此处是None)asyncio.sleep(1)
看成是一个耗时1秒的IO操作,在此期间主线程并未等待,而是去执行EventLoop
中其他可以执行的coroutine
了,因此可以实现并发执行结果如下:
test_1 1
test_1 2
test_2 1
test_2 2
??当yield from
后面加上一个生成器后,就实现了生成的嵌套。
??实现生成器的嵌套,并不是一定必须要使用yield from,而是使用yield from可以让我们避免让我们自己处理各种料想不到的异常,而让我们专注于业务代码的实现。
??如果自己用yield去实现,那只会加大代码的编写难度,降低开发效率,降低代码的可读性。
# 子生成器
def average_gen():
total = 0
count = 0
average = 0
while True:
new_num = yield average
count += 1
total += new_num
average = total/count
# 委托生成器
def proxy_gen():
while True:
yield from average_gen()
# 调用方
def main():
calc_average = proxy_gen()
next(calc_average)# 预激下生成器
print(calc_average.send(10))
print(calc_average.send(20))
print(calc_average.send(30))
main()
结果如下:
10.0
15.0
20.0
委托生成器的作用:
在调用方与子生成器之间建立一个双向通道。
双向通道就是调用方可以通过send()
直接发送消息给子生成器,而子生成器yield的值,也是直接返回给调用方。
??yield from帮我们做了很多的异常处理,而这些如果我们要自己去实现的话,一个是编写代码难度增加,写出来的代码可读性很差,很可能有遗漏,只要哪个异常没考虑到,都有可能导致程序崩溃。
??为了简化并更好地标识异步IO,从Python 3.5开始引入了新的语法async和await,可以让coroutine的代码更简洁易读。
可将上面的案例代码改造如下:
import asyncio
# @asyncio.coroutine
async def test(i):
print('test_1', i)
# r = yield from asyncio.sleep(1)
await asyncio.sleep(1)
print('test_2', i)
loop = asyncio.get_event_loop()
tasks = [test(i) for i in range(1,3)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
执行结果
test_1 1
test_1 2
test_2 1
test_2 2
async
替换 @asyncio.coroutine
,加在def之前用于修饰await
替换yield from
标签:委托 完成 pytho sync 发送消息 进程 参数 python 专注
原文地址:https://www.cnblogs.com/aduner/p/12203626.html