asyncio等待对象 - 基本的例子

The*_*eer 20 python asynchronous python-3.x async-await python-asyncio

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

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

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

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())
Run Code Online (Sandbox Code Playgroud)

我期望的流程是:

  1. 事件循环控制produce_list().produce_list()放弃执行num = await Customer().
  2. Customer()执行并返回一个迭代器.因为返回迭代器中的第一个值.Q1:我不清楚为什么num不成为迭代器本身.这也在做什么send
  3. 一旦达到迭代器的最后一个值.num = 4协程的执行继续print(num),并打印值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
Run Code Online (Sandbox Code Playgroud)

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

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

Vin*_*ent 5

__await__返回一个迭代器,因为协同程序的底层机制最初是基于yield from语法的.在实践中,__await__返回iter(some_future)或者some_coroutine.__await__().它可用于创建每次等待时产生不同值的对象.看这个简单的例子:

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())
Run Code Online (Sandbox Code Playgroud)

回答你的意见:

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

不,asyncio.sleep实际上并不是链条的终点.在最底层,它总是一个正在被屈服的未来:协程链要求事件循环"请在未来有结果时叫醒我".在这种情况下asyncio.sleep,它用于loop.call_later在给定的时间量之后设置未来的结果.环路提供用于调度回调更多的方法:loop.call_at,loop.add_reader,loop.add_writer,loop.add_signal_handler,等.

一个asyncio库,如aiohttp.我假设有些代码不依赖于以前的协同程序的存在.

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

  • 我实际上是想得到一个最终不调用先前定义的 asyncio lib 方法的示例。最后你传递了`await asyncio.sleep(sleep, result=value)`。动机是尝试了解如何编写新的 asyncio 框架。 (2认同)