异步IO、协程、yield from

124 篇文章 0 订阅

上一篇笔记,记录了基础知识,然后继续往下整理。


asyncio标准库,内置了对异步IO的支持:
asyncio编程模型就是一个消息循环。从asyncio模块中直接获取一个EventLoop的引用,然后把需要运行的协程放到EventLoop中执行,就实现了异步IO(不等待IO操作)。

yield from:递归调用Iterable并yield

yield 可以定义一个生成器。

def a():
    for i in range(10):
        yield n

# yield from:
def a():
    yield from range(10)

教程实战部分开始的代码,顺便看yield from

import logging; logging.basicConfig(level=logging.INFO)

import asyncio, os, json, time
from datetime import datetime

from aiohttp import web

def index(request):
    return web.Response(body='<h1>Awesome</h1>'.encode('utf-8'),content_type='text/html')

@asyncio.coroutine
def init(loop):
    app = web.Application(loop=loop)
    app.router.add_route('GET','/',index)  # 添加首页'/'到index()的映射关系
    srv = yield from loop.create_server(app.make_handler(),'127.0.0.1',9000)
    logging.info('server started at http://127.0.0.1:9000...')
    return srv

loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()
  1. loop = asyncio.get_event_loop(),协程不能直接运行,需要把协程加入到事件循环(loop),由loop在适当时候调用协程。这里实例化一个EventLoop,创建一个事件循环。
  2. loop.run_until_complete(init(loop)),将协程注册到事件循环。
  3. @asyncio.coroutine装饰器标明init(loop)是一个协程。
  4. app.router.add_route('GET','/',index) 添加首页'/'index()的映射关系访问首页会调用index()方法来处理客户端请求。
  5. loop.create_server(app.make_handler(),'127.0.0.1',9000),这里创建了TCP Server,这个方法也是一个协程。
  6. yield from(可以替换为await),这里实现了异步IO。协程遇到yield from,事件循环会挂起该协程,执行别的协程,直到其他的协程也挂起或执行完毕,再进行下一个协程的执行。
  7. logging.info(msg, *args, **kwargs): Log a message with severity ‘INFO’ on the root logger.
  8. return srv语句将会从生成器退出并抛出 StopIteration(expr)异常。
  9. web.Response(body='<h1>Awesome</h1>'.encode('utf-8'),content_type='text/html'),这里保证编码是方便查看utf-8,指定网页类型是text/html。浏览器中访问首页,会看到Awesome
  10. 总的来看,上面代码把asyncio用在了服务器端,用单线程+coroutine实现了多用户的高并发支持。

yield from

The full semantics of the yield from expression can be described in terms of the generator protocol as follows:

  • Any values that the iterator yields are passed directly to the caller.
  • Any values sent to the delegating generator using send() are passed directly to the iterator. If the sent value is None, the iterator’s next() method is called. If the sent value is not None, the iterator’s send() method is called. If the call raises StopIteration, the delegating generator is resumed. Any other exception is propagated to the delegating generator.
  • Exceptions other than GeneratorExit thrown into the delegating generator are passed to the throw() method of the iterator. If the call raises StopIteration, the delegating generator is resumed. Any other exception is propagated to the delegating generator.
    If a GeneratorExit exception is thrown into the delegating generator, or the close() method of the delegating generator is called, then the close() method of the iterator is called if it has one. - If this call results in an exception, it is propagated to the delegating generator. Otherwise, GeneratorExit is raised in the delegating generator.
  • The value of the yield from expression is the first argument to the StopIteration exception raised by the iterator when it terminates.
  • return expr in a generator causes StopIteration(expr) to be raised upon exit from the generator.

中文:
1. 迭代器(即可指子生成器)产生的值直接返还给调用者
2. 任何使用send()方法发给委派生产器(即外部生产器)的值被直接传递给迭代器。如果send值是None,则调用迭代器next()方法;如果不为None,则调用迭代器的send()方法。如果对迭代器的调用产生StopIteration异常,委派生产器恢复继续执行yield from后面的语句;若迭代器产生其他任何异常,则都传递给委派生产器。
3. 除了GeneratorExit 异常外的其他抛给委派生产器的异常,将会被传递到迭代器的throw()方法。如果迭代器throw()调用产生了StopIteration异常,委派生产器恢复并继续执行,其他异常则传递给委派生产器。
4. 如果GeneratorExit异常被抛给委派生产器,或者委派生产器的close()方法被调用,如果迭代器有close()的话也将被调用。如果close()调用产生异常,异常将传递给委派生产器。否则,委派生产器将抛出GeneratorExit 异常。
5. 当迭代器结束并抛出异常时,yield from表达式的值是其StopIteration 异常中的第一个参数。
6. 一个生成器中的return expr语句将会从生成器退出并抛出 StopIteration(expr)异常。


更多资料:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值