asyncio等待对象-基本示例 [英] asyncio awaitable object - basic example

查看:106
本文介绍了asyncio等待对象-基本示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图了解如何制作一个可等待的对象. 文档中的定义指出:

I'm trying to understand how to make an awaitable object. The definition from the documentation states:

具有__await__方法的对象返回迭代器.

An object with an __await__ method returning an iterator.

在该定义的指导下,我编写了示例代码:

Guided by that definition I wrote the sample code:

import asyncio

async def produce_list():
        num = await Customer()
        print(num)

class Customer(object):

    def __await__(self):
        return iter([1, 2, 3, 4])

loop = asyncio.get_event_loop()
loop.run_until_complete(produce_list())

我期望的流程是:

  1. 事件循环将控制权交给produce_list(). produce_list()放弃对num = await Customer()的执行.
  2. Customer()被执行并返回一个迭代器.这是因为返回迭代器中的第一个值. Q1:在这里不清楚为什么num不能成为迭代器本身.还有send在这里做什么?
  3. 一旦达到了迭代器的最后一个值. num = 4协程的执行继续到print(num),并输出值4.
  1. Event loop gives control to produce_list(). produce_list() gives up execution on num = await Customer().
  2. Customer() is executed and returns an iterator. Which because returns the first value in the iterator. Q1: am not clear here why num isn't becoming the iterator itself. Also what is doing a send here?
  3. Once the last value the iterator has been reached. num = 4 the execution of the coroutine continues to print(num), and prints the value 4.

我得到了什么:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
~/workspace/dashboard/so_question_await.py in <module>()
     16 
     17 loop = asyncio.get_event_loop()
---> 18 loop.run_until_complete(produce_list())

/usr/lib/python3.5/asyncio/base_events.py in run_until_complete(self, future)
    464             raise RuntimeError('Event loop stopped before Future completed.')
    465 
--> 466         return future.result()
    467 
    468     def stop(self):

/usr/lib/python3.5/asyncio/futures.py in result(self)
    291             self._tb_logger = None
    292         if self._exception is not None:
--> 293             raise self._exception
    294         return self._result
    295 

/usr/lib/python3.5/asyncio/tasks.py in _step(***failed resolving arguments***)
    239                 result = coro.send(None)
    240             else:
--> 241                 result = coro.throw(exc)
    242         except StopIteration as exc:
    243             self.set_result(exc.value)

~/workspace/dashboard/so_question_await.py in produce_list()
      5 
      6 async def produce_list():
----> 7         num = await Customer()
      8         print(num)
      9 

RuntimeError: Task got bad yield: 1

我在这里弄错了什么概念?

What concepts have I gotten wrong here?

最后,我正在寻找一个示例,该示例使用通过列表进行迭代作为事件返回到协程的控件.

In the end I'm looking for an example that uses iteration through a list as an event to return to the control of the coroutine.

推荐答案

__await__返回迭代器,因为协程的基础机制最初是基于yield from语法的.实际上,__await__返回iter(some_future)some_coroutine.__await__().它可以用来创建每次等待时都会产生不同值的对象.参见以下简单示例:

__await__ returns an iterator because the underlying mechanism for coroutines is originally based on the yield from syntax. In practice, __await__ returns either iter(some_future) or some_coroutine.__await__(). It can be used to create objects that produce different values every time they are awaited. See this simple example:

import asyncio
import random

class RandomProducer:

    def __await__(self):
        return self.producer().__await__()

    async def producer(self):
        sleep = random.random()
        value = random.randint(0, 9)
        return await asyncio.sleep(sleep, result=value)

async def main():
    producer = RandomProducer()
    while True:
        print(await producer)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())


回答您的评论:


To answer your comments:

每个协程最终都会调用asyncio.sleep吗?

否,asyncio.sleep实际上不是链的末尾.在最底层,总是有一个未来:协程链要求事件循环请在这个未来有结果时叫醒我".对于asyncio.sleep,它使用loop.call_later设置给定时间后的将来结果.循环提供了更多的计划回调的方法:loop.call_atloop.add_readerloop.add_writerloop.add_signal_handler等.

No, and asyncio.sleep is actually not the end of the chain. At the very bottom, it's always a future that is being yielded: the coroutine chain asks the event loop "please wake me up when this future has a result". In the case of asyncio.sleep, it uses loop.call_later to set the result of the future after a given amount of time. The loop provides more methods for scheduling callbacks: loop.call_at, loop.add_reader, loop.add_writer, loop.add_signal_handler, etc.

一个异步库,例如aiohttp.我假设某个地方的代码不依赖于以前的协程的存在.

An asyncio library such as aiohttp. I'm assuming there is some code somewhere that doesn't rely on existence of previous coroutines.

所有IO操作必须最终委托给事件循环才能实现单线程并发. 例如,aiohttp依赖 loop.create_connection 协程管理TCP连接.

All the IO operations have to end up delegating to the event loop in order to achieve single-threaded concurrency. For instance, aiohttp relies on the loop.create_connection coroutine to manage the TCP connection.

这篇关于asyncio等待对象-基本示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆