通常在IO操作中,我们使用iter()
来读取前哨值:
from sys import stdout
with open(r"Z:\github\StackOverFlow\temp.json", "r") as fp:
for chunk in iter(lambda :fp.read(64), ""):
stdout.write(chunk)
但是iter()
可以代替asyncio.Queue.get()
吗?
for val in iter(lambda: await queue.get(), sentinel):
queue.task_done()
print(val)
这肯定不会起作用,因为它需要可调用,await
不能在非异步函数中调用。
情况不允许queue.get_nowait()
,因为队列在大多数时间都是空的。
简单的解决方法是使用while
循环:
while True:
if (val := await queue.get()) is None:
break
queue.task_done()
print(val)
但是我担心这会损害可读性和清晰度。
答案 0 :(得分:4)
您可以改善与library(reactable)
reactable(iris,
onClick = "select",
selection = "multiple")
循环一起使用的条件,以将海象整合到while
条件中:
while
这可以使您达到所需结果的简洁程度,并且相对于所需的two-arg while (val := await queue.get()) is not None:
queue.task_done()
print(val)
解决方案而言并不是特别丑陋(two-arg iter
在使用中相对丑陋第一名)。
答案 1 :(得分:1)
PEP 525在Python 3.6中引入了异步生成器,实际上在Python 3.7中proposes built-in aiter
and anext
。而且我们知道那没有发生。查看相应的BPO-31861中的讨论,这仍然可能发生,但不早于Python 3.10。
但是有早期实现的CPython BPO PR。仍在讨论它是否应该用Python或C实现,驻留在operator
模块还是builtins
中,但是似乎已经可以使用Python版本了。从908227bb开始,逐字添加代码:
from collections.abc import AsyncIterable, AsyncIterator
_NOT_PROVIDED = object() # sentinel object to detect when a kwarg was not given
def aiter(obj, sentinel=_NOT_PROVIDED):
"""aiter(async_iterable) -> async_iterator
aiter(async_callable, sentinel) -> async_iterator
Like the iter() builtin but for async iterables and callables.
"""
if sentinel is _NOT_PROVIDED:
if not isinstance(obj, AsyncIterable):
raise TypeError(f'aiter expected an AsyncIterable, got {type(obj)}')
if isinstance(obj, AsyncIterator):
return obj
return (i async for i in obj)
if not callable(obj):
raise TypeError(f'aiter expected an async callable, got {type(obj)}')
async def ait():
while True:
value = await obj()
if value == sentinel:
break
yield value
return ait()