Python 在列表中创建任务时的奇怪行为(异步IO) 导入异步IO 随机输入 异步def生成器(q:asyncio.Queue): 对于范围内的uu(100): 等待q.put(random.randint(1,10)) 异步def使用者(q:asyncio.Queue): 尽管如此: num=等待q.get() 打印(“从队列中获取:,num) q、 任务完成() 异步def main(): q=asyncio.Queue() pr=asyncio.create_任务(生产者(q)) consumers=[asyncio.create_任务(consumer(q))用于范围(10)] 等待公关 等待q.加入() 对于消费者中的c: c、 取消 asyncio.run(main())
我创建这个脚本是为了复制问题的简化版本。 所以这是一个非常基本的生产者-消费者类型的脚本,它工作得很好 但是,如果使用者内部发生异常,脚本将冻结。 例如,如果我这样修改使用者脚本:Python 在列表中创建任务时的奇怪行为(异步IO) 导入异步IO 随机输入 异步def生成器(q:asyncio.Queue): 对于范围内的uu(100): 等待q.put(random.randint(1,10)) 异步def使用者(q:asyncio.Queue): 尽管如此: num=等待q.get() 打印(“从队列中获取:,num) q、 任务完成() 异步def main(): q=asyncio.Queue() pr=asyncio.create_任务(生产者(q)) consumers=[asyncio.create_任务(consumer(q))用于范围(10)] 等待公关 等待q.加入() 对于消费者中的c: c、 取消 asyncio.run(main()),python,python-asyncio,Python,Python Asyncio,我创建这个脚本是为了复制问题的简化版本。 所以这是一个非常基本的生产者-消费者类型的脚本,它工作得很好 但是,如果使用者内部发生异常,脚本将冻结。 例如,如果我这样修改使用者脚本: async def使用者(q:asyncio.Queue): 引发异常 尽管如此: num=等待q.get() 打印(“从队列中获取:,num) q、 任务完成() 当我现在运行脚本时,它会冻结,不会抛出异常。 但是,如果我将主脚本更改为在for循环中生成所有使用者任务,而不是通过如下列表理解生成它们: async
async def使用者(q:asyncio.Queue):
引发异常
尽管如此:
num=等待q.get()
打印(“从队列中获取:,num)
q、 任务完成()
当我现在运行脚本时,它会冻结,不会抛出异常。
但是,如果我将主脚本更改为在for循环中生成所有使用者任务,而不是通过如下列表理解生成它们:
async def main():
q=asyncio.Queue()
pr=asyncio.create_任务(生产者(q))
#consumers=[asyncio.create_任务(consumer(q))用于范围(10)]
对于范围(10)内的uu:
asyncio.create_任务(消费者(q))
等待公关
等待q.加入()
它抛出10个类型为Exception的异常,这是预期的行为。
我的两个问题是:
我不认为使用列表理解而不是for循环对此有任何影响 您应该在使用者中处理异常,并为每个
get()
调用task\u done()
,否则您将体验当前行为,其中q.join()
将阻止/等待未完成的任务:
如果join()当前处于阻塞状态,则当所有项都已被阻塞时,它将恢复
已处理(意味着每个
已放入()队列的项)
test.py:
import asyncio
import random
async def producer(q):
for _ in range(10):
await q.put(random.randint(1, 10))
async def consumer(q):
while True:
num = await q.get()
try:
if num in (5, 8):
raise Exception("ERROR")
print(f"Working on: {num}")
except Exception as exc:
print(f"{num}: {exc}")
finally:
q.task_done()
async def main():
q = asyncio.Queue()
pr = asyncio.create_task(producer(q))
tasks = []
for _ in range(10):
tasks.append(asyncio.create_task(consumer(q)))
await pr
await q.join()
for task in tasks:
task.cancel()
await asyncio.gather(*tasks, return_exceptions=True)
if __name__ == "__main__":
asyncio.run(main())
$ python test.py
Working on: 7
Working on: 4
Working on: 4
Working on: 4
Working on: 1
Working on: 3
8: ERROR
Working on: 6
5: ERROR
Working on: 4
测试:
import asyncio
import random
async def producer(q):
for _ in range(10):
await q.put(random.randint(1, 10))
async def consumer(q):
while True:
num = await q.get()
try:
if num in (5, 8):
raise Exception("ERROR")
print(f"Working on: {num}")
except Exception as exc:
print(f"{num}: {exc}")
finally:
q.task_done()
async def main():
q = asyncio.Queue()
pr = asyncio.create_task(producer(q))
tasks = []
for _ in range(10):
tasks.append(asyncio.create_task(consumer(q)))
await pr
await q.join()
for task in tasks:
task.cancel()
await asyncio.gather(*tasks, return_exceptions=True)
if __name__ == "__main__":
asyncio.run(main())
$ python test.py
Working on: 7
Working on: 4
Working on: 4
Working on: 4
Working on: 1
Working on: 3
8: ERROR
Working on: 6
5: ERROR
Working on: 4