前言

最近,花了一个月多的时间,终于看完了Fluent Python,这本书真是Python进阶的必备书。里面有很多看一遍不一定的能懂得,得多看几遍。这篇文章主要整理一下Pyhton协程部分。

协程

定义

协程是指一个过程,这个过程与调用方协作,产出由调用方提供的值。在python中,使用yield关键字,生成器.send(value)。生成器的调用方可以使用.send方法发送数据,发送的数据会成为生成器函数中yield表达式的值。

状态

协程有4个状态,可以使用inspect.getgeneratorstate(…)函数确定。

  • GEN_CREATED # 等待开始执行
  • GEN_RUNNING # 解释器正在执行(只有在多线程应用中才能看到这个状态)
  • GEN_SUSPENDED # 在yield表达式处暂停
  • GEN_CLOSED # 执行结束

最先调用next()函数这一步通常称为”预激”,让协程向前执行到第一个yield表达式。

yield from

yield from 是python3.3新加的语言结构,python3.5使用await,起主要功能是打开双向通道,把最外层的调用方与最内层的子生成器连接起来,这样二者可以直接发送和产出值,还可以传入异常。其会在内部自动捕获stopiteation异常。其主要包括:

  • 委派生成器 包含yield from iterable 表达式的生成器函数
  • 子生成器 指委派生成器中的iterable
  • 调用方

asyncio

使用asyncio+yield from 实现异步IO,asyncio是使用事件循环驱动的协程实现并发。事件循环指一种等待程序分配事件或消息的编程架构。

import asyncio

async def hello():
    r = yield from asyncio.sleep(2)
    return ''

loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
loop.close()

aiohttp

aiohttp是基于asyncio实现的http客户端和服务器。https://github.com/itswcg/learn-aiohttp是我写的一个基于aiohttp+aiomysql的服务器和客户端。客户端大体测试,请求同一个网址500次,普通的requests要几分钟,而aiohttp只要10秒。服务端大体测试,往aiohttp+aiomysql服务端post数据,使用aiohttp客户端,插入5000条,大约15秒。ps:本地测试,单线程。

参考

https://github.com/itswcg/Books/blob/master/%E6%B5%81%E7%95%85%E7%9A%84python.pdf>
http://blog.gusibi.com/post/python-asyncio-server/
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432090954004980bd351f2cd4cc18c9e6c06d855c498000