Python Coroutine 初探
2015-11-22 16:06
671 查看
原文链接:http://whosemario.github.io/2015/11/22/python-coroutine/
This PEP proposes some enhancements to the API and syntax of generators, to make them usable as simple coroutines.
在Python2.x,我们可以用Generator来实现Coroutine的功能。
上面是一个coroutine的修饰器,如下是使用此修饰器的方法。
其实python在编译grep这段代码的时候,发现有yield关键字,func_code的co_flags会存在CO_GENERATOR标志位,因此在PyEval_EvalCodeEx执行的过程中会返回一个generator实例,而不是去执行这个函数的func_code。generator实例中会保存对应的PyFrameObject。
在generator的send方法中会继续运行此时保存的PyFrameObject。
当async def函数里面调用await的时候,这个coroutine将会被挂起(Suspended)。但看Python3.5的源码后发现,coroutine的内部实现和generator的内部实现基本相同。
上面是coroutine的PyTypeObject的定义,其实一开始的示例代码中print_sum函数返回的正是一个coroutine实例(是不是跟generator很像呢?!)。我们在看一下coro_methods的定义。
send方法的实现就是_PyGen_Send,和generator的实现一模一样,await后面可以紧跟一个新的coroutine实例,这个功能则归功于Python3.3开始出现的yield from语法。
PEP380 - https://docs.python.org/3/whatsnew/3.3.html#pep-380
A Curious Course on Coroutines and Concurrency - http://www.dabeaz.com/coroutines/Coroutines.pdf
从Python2.5开始
首先引用PEP342开篇的一段话This PEP proposes some enhancements to the API and syntax of generators, to make them usable as simple coroutines.
在Python2.x,我们可以用Generator来实现Coroutine的功能。
def coroutine(func): def wrapper(*args, **kwargs): cr = func(*args, **kwargs) try: cr.next() except StopIteration: pass return cr return wrapper
上面是一个coroutine的修饰器,如下是使用此修饰器的方法。
@coroutine def grep(pattern): print "Looking for %s" % pattern while True: line = (yield) if pattern in line: print line, g = grep("hello") g.send("hello world") g.send("test hello") g.send("test world")
其实python在编译grep这段代码的时候,发现有yield关键字,func_code的co_flags会存在CO_GENERATOR标志位,因此在PyEval_EvalCodeEx执行的过程中会返回一个generator实例,而不是去执行这个函数的func_code。generator实例中会保存对应的PyFrameObject。
PyObject * PyGen_New(PyFrameObject *f) { PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type); ... ... gen->gi_frame = f; Py_INCREF(f->f_code); gen->gi_code = (PyObject *)(f->f_code); gen->gi_running = 0; gen->gi_weakreflist = NULL; _PyObject_GC_TRACK(gen); return (PyObject *)gen; }
在generator的send方法中会继续运行此时保存的PyFrameObject。
static PyObject * gen_send_ex(PyGenObject *gen, PyObject *arg, int exc) { PyThreadState *tstate = PyThreadState_GET(); PyFrameObject *f = gen->gi_frame; PyObject *result; ... ... result = PyEval_EvalFrameEx(f, exc); ... ... return result }
Python3.3的yield from
Python3.3针对Generator加入了新的语法yield from,个人感觉新的语法可以让某些功能的实现更新简洁(其实就是少写点代码啊,,,),但真正本质上并没有改善Generator。这篇文章对yield from语法做了一定的解释。Python3.5 async def
Python3.5引入了async def语法,定义一个coroutine。import asyncio async def compute(x, y): print("Compute %s + %s ..." % (x, y)) await asyncio.sleep(1.0) return x + y async def print_sum(x, y): result = await compute(x, y) print("%s + %s = %s" % (x, y, result)) loop = asyncio.get_event_loop() loop.run_until_complete(print_sum(1, 2)) loop.close()
当async def函数里面调用await的时候,这个coroutine将会被挂起(Suspended)。但看Python3.5的源码后发现,coroutine的内部实现和generator的内部实现基本相同。
# genobject.c PyTypeObject PyCoro_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "coroutine", /* tp_name */ ... coro_methods, /* tp_methods */ ... };
上面是coroutine的PyTypeObject的定义,其实一开始的示例代码中print_sum函数返回的正是一个coroutine实例(是不是跟generator很像呢?!)。我们在看一下coro_methods的定义。
static PyMethodDef coro_methods[] = { {"send",(PyCFunction)_PyGen_Send, METH_O, coro_send_doc}, {"throw",(PyCFunction)gen_throw, METH_VARARGS, coro_throw_doc}, {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc}, {NULL, NULL} /* Sentinel */ };
send方法的实现就是_PyGen_Send,和generator的实现一模一样,await后面可以紧跟一个新的coroutine实例,这个功能则归功于Python3.3开始出现的yield from语法。
references:
PEP342 - https://www.python.org/dev/peps/pep-0342/PEP380 - https://docs.python.org/3/whatsnew/3.3.html#pep-380
A Curious Course on Coroutines and Concurrency - http://www.dabeaz.com/coroutines/Coroutines.pdf
相关文章推荐
- S折交叉验证 in Python
- 用python 爬糗事百科的段子-1
- python3爬虫问题 POST data should be bytes or an iterable of bytes
- Python抓取淘女郎网页信息以及代码下载
- python的编码问题研究------使用scrapy体验
- [Python]利用python爬虫去LeetCode上下载Ac解
- 如何在cmd命令下运行python脚本
- installation about python package and complier
- windows下selenium+python环境搭建
- Python 运算符
- Python 变量类型
- Python 基础语法
- Python 中文编码
- Python 环境搭建
- Python 简介
- Python 快速教程(Django07):马不停蹄
- Python 快速教程(Django06):假作真时
- Python 快速教程(Django05):黑面管家
- Python 快速教程(Django03): 所谓伊人
- Python 快速教程(Django02):庄园疑云