深入Asyncio(四)Coroutines
Coroutines
asyncio在3.4版本添加到Python中,但通过
async def和await关键字创建coroutines的语法是3.5才加入的,在这之前,人们把generators当作coroutines来使用,在一些老的语法中,你可以看到用@asyncio.coroutine之类的装饰器加yield的句式,在本文中,请摒弃过去的写法。
async def关键字
>>> async def f():    # 1
...     return 123
>>> type(f)    # 2
<class 'function'>
>>> import inspect    # 3
>>> inspect.iscoroutinefunction(f)
True
- 这是声明coroutine的最简单方式;
 - 与生成器函数的判定一样,coroutine也会被判定为协程函数,只有在调用这个函数时才能获得协程,就如生成器一样;
 - 标准库中的检查模块可以提供比type方法更好的内省能力。
 
正是由于在3.4版本用生成器当作协程来使用,所以在3.5版本中,async def的用法以及效果与生成器几乎相同。我们通过代码来观察Python如何在不同协程中切换,首先先看下如何获得return的值。
当coroutine return的时候,将会抛出一个StopIteration异常。
>>> async def f():
...     return 123
>>> coro = f()
>>> try:
...     coro.send(None)    # 1
... except StopIteration as e:
...     print('The answer was: ', e.value)    # 2
The answer was:  123
- coroutine通过发送None来启动,这就是loop在背后做的事;
 - 协程返回时抛出StopIteration异常,可以通过异常的value属性访问返回值。
 
协程的开始和结束是通过send()和StopIteration来定义的,loop负责在背后做这些事,开发者只需要为loop安排task即可。
await关键字
await关键字总是接收一个参数,其类型必须是awaitable的,必须是如下两种之一:
1. 一个coroutine;
2. 一个实现了__await__()方法的对象,这个方法必须返回一个迭代器。
async def f():
    await asyncio.sleep(1.0)
    return 123
async def main():
    result = await f()  # 1
    return result
- 这里调用了f函数返回了一个coroutine。
 
在开始学习loop之前,了解一下如何向协程提供异常很有用,异常通常用于取消协程,在task.cancel()时,loop在内部使用coro.throw()来抛出一个asyncio.CancelledError。
>>> coro = f()  # 使用上面的协程
>>> coro.send(None)
<Future pending>
>>> coro.throw(Exception, 'hello')  # 通过throw方法提供一个异常和值,该异常将在await处产生
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
Exception: hello
>>> async def f():
...     try:
...             while True: await asyncio.sleep(0)
...     except asyncio.CancelledError:
...             print('I was cancelled!')
...     else:
...             return 111
>>> coro = f()
>>> coro.send(None)
>>> coro.send(None)
>>> coro.throw(asyncio.CancelledError)
I was cancelled!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration   # 正是由于内部捕捉了CancelledError,这个协程得以正常退出
>>> import asyncio
>>> async def f():
...     try:
...             while True: await asyncio.sleep(0)
...     except asyncio.CancelledError:
...             print('Cancelled')
...             while True: await asyncio.sleep(0)  # 跳转到另一个协程上去了
...     else: return 1
>>> coro = f()
>>> coro.send(None)
>>> coro.throw(asyncio.CancelledError)
Cancelled
>>> coro.send(None)
目前为止的代码中,都是通过手动调用send(None)和throw(asyncio.CancelledError)来模拟loop的,下一章开始学习用loop来自动处理。
>>> async def f():
...     await asyncio.sleep(0)
...     return 123
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(f())
123												
											深入Asyncio(四)Coroutines的更多相关文章
- asyncio之Coroutines,Tasks and Future
		
asyncio之Coroutines,Tasks and Future Coroutines and Tasks属于High-level APIs,也就是高级层的api. 本节概述用于协程和任务的高级 ...
 - Python标准模块--asyncio
		
1 模块简介 asyncio模块作为一个临时的库,在Python 3.4版本中加入.这意味着,asyncio模块可能做不到向后兼容甚至在后续的Python版本中被删除.根据Python官方文档,asy ...
 - 【译】深入理解python3.4中Asyncio库与Node.js的异步IO机制
		
转载自http://xidui.github.io/2015/10/29/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3python3-4-Asyncio%E5%BA%93% ...
 - Understanding Asynchronous IO With Python 3.4's Asyncio And Node.js
		
[转自]http://sahandsaba.com/understanding-asyncio-node-js-python-3-4.html Introduction I spent this su ...
 - aiohttp/asyncio 多次请求
		
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = "Daniel Altiparmak (sixfinger78@gmai ...
 - 7.Python3标准库--文件系统
		
''' Python的标准库中包含大量工具,可以处理文件系统中的文件,构造和解析文件名,还可以检查文件内容. 处理文件的第一步是要确定处理的文件的名字.Python将文件名表示为简单的字符串,另外还提 ...
 - Python高性能HTTP客户端库requests的使用
		
Python中有许多HTTP客户端.使用最广泛且最容易的是requests. 持续连接 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...
 - Python之路(第四十七篇) 协程:greenlet模块\gevent模块\asyncio模块
		
一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 协程相比于线程,最大的区别在于 ...
 - 关于asyncio知识(四)
		
一.使用 asyncio 总结 最近在公司的一些项目中开始慢慢使用python 的asyncio, 使用的过程中也是各种踩坑,遇到的问题也不少,其中有一次是内存的问题,自己也整理了遇到的问题以及解决方 ...
 
随机推荐
- AJAX在VS2005中的简单应用 使用ajaxpro.2.dll[点击按钮执行事件不刷新]
			
原文发布时间为:2008-10-21 -- 来源于本人的百度文章 [由搬家工具导入] 1.下載ajaxpro.dll或AjaxPro.2.dll 放在Bin文件夹中2.配置web.config 3.u ...
 - 浮点优化选项 -ffast-math:极大地提高浮点运算速度【转】
			
转自:http://blog.csdn.net/zjujoe/article/details/2604157 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 关于浮点优化选项摘 ...
 - TCO 2015 Round 2A DIV1
			
ModModMod 傻逼数论 题意: 这是一道卖萌的题..给你一个取模序列$m$,令$f(x)=(\cdots (x\ mod\ m[0])\ mod m[1])\mod m[2]\cdots $,问 ...
 - ACM的奇计淫巧_输入挂
			
什么是输入挂? 众所周知scanf比cin快的多,那么有没有比scanf更快的东西呢?答案就是输入挂,输入挂利用了告诉读取的函数getchar(),然后再人工处理成整数或浮点,比使用scanf快太多. ...
 - [TJOI2014] Alice and Bob
			
非常好的一道思维性题目,想了很久才想出来qwq(我好笨啊) 考虑a[]数组有什么用,首先可以yy出一些性质 (设num[i]为原来第i个位置的数是什么 , 因为题目说至少有一个排列可以满足a[],所以 ...
 - mysql之select,insert,delete,update
			
写在前面 上篇文章学习了创建数据库和数据表,这篇文章将学习对数据表的增删改查操作. 系列文章 mysql之创建数据库,创建数据表 一个例子 上篇文章中,创建了数据库和数据表,数据表中还没有数据,这里我 ...
 - 动态设置表格[GridView]在编辑时 只读。
			
找到GridView的CellEditorInitalize事件. protected void agv_main_CellEditorInitialize(object sender, ASPxGr ...
 - 前台页面获取servlet传过来的数据
			
servlet中的代码: public void doGet(HttpServletRequest request, HttpServletResponse response) throws Serv ...
 - 前端模板adminlte
			
adminlet是一个前端模板,包含各种各样的功能,自己的网站可以根据需要进行修改:可以免费使用,也有收费增强版,界面如下: 参考: 1.https://adminlte.io/ 2.https:// ...
 - GEOS 使用的例子
			
typedef Coordinate PT;geos::geom::Geometry* CGlbGlobePolygonSymbol::Interection(CGlbPolygon *geom, C ...