python异步函数 python异步执行命令( 三 )


异步编程虽然很不错 , 不过,也许你并不需要 。
python异步有哪些方式yield相当于return,他将相应的值返回给调用next()或者send()的调用者 , 从而交出了CPU使用权,而当调用者再次调用next()或者send()的时候,又会返回到yield中断的地方,如果send有参数,还会将参数返回给yield赋值的变量,如果没有就和next()一样赋值为None 。但是这里会遇到一个问题,就是嵌套使用generator时外层的generator需要写大量代码,看如下示例:
注意以下代码均在Python3.6上运行调试
#!/usr/bin/env python# encoding:utf-8def inner_generator():
i = 0
while True:
i = yield iif i10:raise StopIterationdef outer_generator():
print("do something before yield")
from_inner = 0
from_outer = 1
g = inner_generator()
g.send(None)while 1:try:
from_inner = g.send(from_outer)
from_outer = yield from_innerexcept StopIteration:breakdef main():
g = outer_generator()
g.send(None)
i = 0
while 1:try:
i = g.send(i + 1)
print(i)except StopIteration:breakif __name__ == '__main__':
main()1234567891011121314151617181920212223242526272829303132333435363738394041
为了简化,在Python3.3中引入了yield from
yield from
使用yield from有两个好处,
1、可以将main中send的参数一直返回给最里层的generator,
2、同时我们也不需要再使用while循环和send (), next()来进行迭代 。
我们可以将上边的代码修改如下:
def inner_generator():
i = 0
while True:
i = yield iif i10:raise StopIterationdef outer_generator():
print("do something before coroutine start")yield from inner_generator()def main():
g = outer_generator()
g.send(None)
i = 0
while 1:try:
i = g.send(i + 1)
print(i)except StopIteration:breakif __name__ == '__main__':
main()1234567891011121314151617181920212223242526
执行结果如下:
do something before coroutine start123456789101234567891011
这里inner_generator()中执行的代码片段我们实际就可以认为是协程,所以总的来说逻辑图如下:
接下来我们就看下究竟协程是啥样子
协程coroutine
协程的概念应该是从进程和线程演变而来的,他们都是独立的执行一段代码,但是不同是线程比进程要轻量级,协程比线程还要轻量级 。多线程在同一个进程中执行,而协程通常也是在一个线程当中执行 。它们的关系图如下:
我们都知道Python由于GIL(Global Interpreter Lock)原因 , 其线程效率并不高,并且在*nix系统中,创建线程的开销并不比进程?。虼嗽诓⒎⒉僮魇? ,多线程的效率还是受到了很大制约的 。所以后来人们发现通过yield来中断代码片段的执行 , 同时交出了cpu的使用权,于是协程的概念产生了 。在Python3.4正式引入了协程的概念,代码示例如下:
import asyncio# Borrowed fromcountdown(number, n):
while n0:
print('T-minus', n, '({})'.format(number))yield from asyncio.sleep(1)
n -= 1loop = asyncio.get_event_loop()
tasks = [
asyncio.ensure_future(countdown("A", 2)),
asyncio.ensure_future(countdown("B", 3))]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()12345678910111213141516
示例显示了在Python3.4引入两个重要概念协程和事件循环,
通过修饰符@asyncio.coroutine定义了一个协程,而通过event loop来执行tasks中所有的协程任务 。之后在Python3.5引入了新的asyncawait语法 , 从而有了原生协程的概念 。
asyncawait
在Python3.5中,引入了ayncawait 语法结构,通过”aync def”可以定义一个协程代码片段 , 作用类似于Python3.4中的@asyncio.coroutine修饰符,而await则相当于”yield from” 。

推荐阅读