我正在努力了解如何制作一个等待的对象。来自documentation的定义:
使用__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())
我期待的流程是:
produce_list()
。 produce_list()
放弃了num = await Customer()
。Customer()
被执行并返回一个迭代器。因为返回迭代器中的第一个值。 Q1: 这里不清楚为什么num
没有成为迭代器本身。这也是send
在这里做什么的? 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
我在这里犯了什么概念?
最后,我正在寻找一个示例,它使用列表中的迭代作为事件返回到协程的控制。
答案 0 :(得分: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())
回答你的意见:
每个协程最终都会调用
asyncio.sleep
吗?
不,asyncio.sleep
实际上不是链的末尾。在最底层,它总是一个正在产生的未来:协程链要求事件循环“请在未来有结果时叫醒我”。在asyncio.sleep
的情况下,它使用loop.call_later
在给定的时间量后设置未来的结果。循环提供了更多调度回调的方法:loop.call_at
,loop.add_reader
,loop.add_writer
,loop.add_signal_handler
等。
asioio库,例如aiohttp。我假设有些代码不依赖于以前的协同程序的存在。
所有IO操作都必须最终委托给事件循环才能实现单线程并发。 例如,aiohttp依赖于loop.create_connection协程到manage the TCP connection。