python的异步io编程

这两天在进行node的编码工作,使用node的awiat异步编程是真滴爽,在py3.5之后也可以使用await关键字后,于是对于python的异步编程这一块又开始兴趣浓厚起来。

一、

协程

说起py的异步编程,就要先谈起协程这一概念。

协程在py3.4被正式引入,其中和它一样重要的概念是事件循环

总所周知,线程是比进程要轻量级的,这里,协程更比线程还要轻量级。 另外,py的多线程是坑爹的,不同于静态语言java,c#这些的多线程,py的多线程的性能要差的多,因为从根源来说,py的多线程其实是假的,只是线程工作切换很快,其实都是单线程在工作。 还有,py在linux的环境下,创建线程损耗的资源是与进程相差无几的。 协程的好处不仅是避免了线程的死锁,变量的统一性的问题,更是少了线程切换的开销。 所以在需要线程数越多的情况下,使用协程来异步编程,更加方便快捷,环保节约。

二、

yield

使用yield关键字创建的生成器在被一个外部生成器调用的时候,它就是一个协程。

概述:yield有一半return的功能,它将相应的值返回给调用next()或者send()的调用者,从而交出了CPU使用权,而当调用者再次调用next()或者send()的时候,又会返回到yield中断的地方,如果send有参数,还会将参数返回给yield赋值的变量,如果没有就和next()一样赋值为None。每次 next() 被调用时,生成器回复它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值),另一个关键的功能在于两次执行之间,局部变量和执行状态都自动的保存下来。这使函数很容易写,而且 比使用 self.index 和 self.data 之类的方式更清晰。除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出 StopIteration 异常。综上所述,这个功能使得编写一个正规函数成为创建迭代器的最简单方法。

注意,第一次必须send(None)来开启协程

示例:

def bottom():
    i = 0
    while True:
        i = yield i
        print(i)
        if i > 3:
            raise StopIteration


def main():
    b = bottom()
    b.send(None)
    i = 0
    while 1:
        try:
            i = b.send(i + 1)
        except StopIteration:
            break


if __name__ == '__main__':
    main()

 

三、

yield form

为了让生成器(带yield函数),能简易的在其他函数中直接调用,在Python3.3中引入了yield from。

示例:

def bottom():
    i = 0
    while True:
        i = yield i
        print(i)
        if i > 3:
            raise StopIteration


def top():
    j = yield from bottom()
    print(j)


def main():
    b = top()
    b.send(None)
    i = 0
    while 1:
        try:
            i = b.send(i + 1)
        except StopIteration:
            break


if __name__ == '__main__':
    main()

在上述代码增加了top函数,此时使用了yield form后,top成为了一个新的生成器。

四、

async/await

在Python3.5中,引入了aync&await 语法结构,通过"aync def"可以定义一个协程代码片段,作用类似于Python3.4中的@asyncio.coroutine修饰符,而await则相当于"yield from"。

示例:

import asyncio
import aiohttp


async def bottom(i):
    print(i)


async def main():
    await asyncio.wait([
        bottom(1),
        bottom(2),
        bottom(3)
    ])


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

 

要注意的是,并不是使用了async,await就实现了异步,这里还需要使用必须使用支持异步操作的非阻塞代码才能实现真正的异步,例如非阻塞异步I/O的库aiohttp,主要用于网络传输,同于request,这个库在服务端能发挥的性能威力让人侧目。上面示例没有给出。

异步编程还有更加强大的库支撑,例如uvloop,后面会再记载,现在可去https://magic.io/blog/uvloop-blazing-fast-python-networking/

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值