如何在Python 3.8中为asyncio.gather构建任务列表



下面我附加了一个测试程序来演示我在asyncio.collecte抛出TypeError时遇到的问题。

我的目标: 进行多个并发异步调用,将相机图像捕获到连接到我计算机的USB相机阵列中的文件中。当所有的相机都完成了异步捕获后,我想继续处理

这里显示的异步协程take_image(("ffmpeg">将图像从指定相机捕获到指定文件的应用程序。

import asyncio
import os
import subprocess
import time
async def take_image(camera_id, camera_name, image_file_path, image_counter):
    image_capture_tic = time.perf_counter()
    try:
        run_cmd = subprocess.run( ["ffmpeg", '-y', '-hide_banner', '-f', 'avfoundation', '-i', camera_id,
                                   '-frames:v', '1', '-f', 'image2', image_file_path], universal_newlines=True,
                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)  # Note, ffmpeg writes to stderr, not stdout!
    except Exception as e:
        print("Error: Unable to capture image for", image_file_path)
        return "NO IMAGE!"
    image_capture_toc = time.perf_counter()
    print(f"{image_counter}: Captured {camera_name} image in: {image_capture_toc - image_capture_tic:0.0f} seconds")
    return camera_name

下面显示的main((例程获取多个相机的列表,并在列表中的每个相机上迭代,main((使用asyncio.create_task((每个相机创建一个异步任务。每个任务都添加到任务列表中。

一旦所有的图像捕获任务都启动了,我就使用wait-asyncio.gate(tasks(.等待它们的完成

async def main():
    tic = time.perf_counter()
    camera_list = [('0', 'FHD Camera #1'),  ('1', 'FHD Camera #2'), ('2', 'FHD Camera #3'), ]
    image_counter = 1
    tasks = []
    for camera_pair in camera_list:
        camera_id, camera_name = camera_pair
        image_file_name = 'img' + str(image_counter) + "-cam" + str(camera_id)  + "-" + camera_name + '.jpg'
        image_file_path = os.path.join("/tmp/test1/img", image_file_name)
        # schedule all image captures calls *concurrently*:
        tasks.append(asyncio.create_task(take_image(camera_id, camera_name, image_file_path, image_counter),
                     name=image_file_name))
        image_counter = image_counter + 1
    await asyncio.gather(tasks) # <-- This line throws a TypeError!
    toc = time.perf_counter()
    print(f"Captured list of {image_counter - 1} cameras in: {toc - tic:0.0f} seconds")
asyncio.run(main())

不幸的是,当我试图运行这个程序时,我得到了这个错误:

类型错误:不可更改的类型:'list'

以及以下回溯:

Traceback (most recent call last):
  File "scratch_10.py", line 41, in <module>
    asyncio.run(main())
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/base_events.py", line 608, in run_until_complete
    return future.result()
  File "scratch_10.py", line 36, in main
    await asyncio.gather(tasks)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/tasks.py", line 805, in gather
    if arg not in arg_to_fut:
TypeError: unhashable type: 'list'

我一直试图弄清楚asyncio的3.8文档,但我不明白哪里出了问题。

如何让每个take_image请求异步运行,然后在每个任务完成后恢复调用例程中的处理?

gather采用位置参数,而不是单个可迭代参数。你需要打开你的清单。

await asyncio.gather(*tasks)

您应该尝试:(任务1、任务2、任务3(这就是我为任务所做的,它起作用了

相关内容

  • 没有找到相关文章

最新更新