[英]asyncio.gather with generator expression
Why doesn't asyncio.gather work with a generator expression?为什么 asyncio.gather 不能与生成器表达式一起使用?
import asyncio
async def func():
await asyncio.sleep(2)
# Works
async def call3():
x = (func() for x in range(3))
await asyncio.gather(*x)
# Doesn't work
async def call3():
await asyncio.gather(func() for x in range(3))
# Works
async def call3():
await asyncio.gather(*[func() for x in range(3)])
asyncio.run(call3())
The second variant gives:第二种变体给出:
[...]
File "test.py", line 13, in <genexpr>
await asyncio.gather(func() for x in range(3))
RuntimeError: Task got bad yield: <coroutine object func at 0x10421dc20>
Is this expected behavior?这是预期的行为吗?
await asyncio.gather(func() for x in range(3))
This doesn't work because this is passing the generator object as argument to gather
.这不起作用,因为这将生成器 object作为参数传递给gather
。 gather
doesn't expect an iterable , it expects coroutines as individual arguments. gather
不期望一个可迭代的,它期望协程作为单独的 arguments。 Which means you need to unpack the generator.这意味着您需要打开生成器的包装。
Unpack the generator:打开生成器的包装:
await asyncio.gather(*(func() for i in range(10))) # star expands generator
We must expand it because asyncio.gather
expects a list of arguments (ie asyncio.gather(coroutine0, coroutine1, coroutine2, coroutine3)
), not an iterable我们必须扩展它,因为asyncio.gather
需要一个 arguments 列表(即asyncio.gather(coroutine0, coroutine1, coroutine2, coroutine3)
),而不是一个可迭代的
Python uses *
/ **
for both 'un-packing' and just 'packing' based on whether it's used for variable assignment or not. Python 使用*
/ **
用于“解包”和“打包”,具体取决于它是否用于变量赋值。
def foo(*args,**kwargs):...
In this case, all non-keyworded args are getting put into a tuple args
and all kwargs are getting packed into a new dictionary.在这种情况下,所有非关键字 args 都被放入一个元组args
中,所有 kwargs 都被打包到一个新字典中。 A single variable passed in still gets packed into a tuple( *
) or dict( **
).传入的单个变量仍被打包到元组( *
)或字典( **
)中。
This is kind of a hybrid这是一种混合
first,*i_take_the_rest,last = range(10)
>>> first=0,i_take_the_rest=[1,2,3,4,5,6,7,8],last=9
*a,b = range(1)
>>> a=[],b=0
But here it unpacks:但在这里它解包:
combined_iterables = [*range(10),*range(3)]
merged_dict = {**first_dict,**second_dict}
So basically if it's on the left side of the equals or if it's used in a function/method definition like *foo
it's packing stuff into a list or tuple (respectively).所以基本上,如果它位于等号的左侧,或者如果它用于像*foo
这样的函数/方法定义中,它会将内容打包到列表或元组中(分别)。 In comprehensions, however, it has the unpacking behavior.然而,在理解中,它具有解包行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.