异步遍历两个列表?

traverse two lists asynchronously?

提问人:jhown 提问时间:12/8/2022 更新时间:12/8/2022 访问量:89

问:

我有两个列表,lzma2_list 和 rar_list。两者都具有随机数量的对象名称,这些名称每天都在变化。这些对象所在的目录名为“O:”,有 2 种方法可以处理此数据。

bkp.zipto_rar(path,object_name)
bkp.zipto_lzma(path,object_name)

如何在不等待一个项目完成的情况下异步获取列表中的所有项目?

使用异步列表和线程加速压缩 我尝试使用这个问题的答案,但在我的情况下,这些方法接收 2 个参数,一个是固定的,指的是目录,另一个会不断变化,指的是列表中的项目。


python 列表 异步 async-await python-asyncio

评论

0赞 ruohola 12/8/2022
做什么和做什么?是 IO 还是 CPU 绑定工作?bkp.zipto_rarbkp.zipto_lzma
0赞 CtrlZ 12/8/2022
我希望这些操作受 CPU 限制。因此,多处理将是您的最佳选择
0赞 Paul Cornelius 12/8/2022
问题是你想使用map函数,但你需要传递两个参数而不是一个?然后解决方案是使用 functools.partial 创建一个第一个参数固定的新函数。

答:

0赞 Jaŭhieni Harochaŭ 12/8/2022 #1

由于函数采用参数,因此应使用参数将其转换为不带参数的签名。functools.partial

然后,如果函数受 IO 限制,则可以用于处理后台线程中的每个项目,或者如果函数受 CPU 限制,则可以用于处理后台进程中的项目。asyncio.new_event_loop().run_in_executormultiprocessing.Pool

您甚至可以将两种方法结合起来,并在每个后台进程中使用许多 theads,但是在不知道具体细节或您的函数和列表的情况下很难写出有用的示例。之后收集结果也可能不是一件小事。

import asyncio
import functools

lzma2_list = []
rar_list = []


def process_lzma2_list():
    path = 'CONST'
    for item in lzma2_list:
        func = functools.partial(bkp.zipto_lzma, *(path, item))
        asyncio.new_event_loop().run_in_executor(executor=None, func=func)


def process_rar_list():
    path = 'CONST'
    for item in rar_list:
        func = functools.partial(bkp.zipto_rar, *(path, item))
        asyncio.new_event_loop().run_in_executor(executor=None, func=func)
        

if __name__ == '__main__':
    # it's ok to run these 2 functions sequentially as they just create tasks, actual processing is done in background
    process_lzma2_list()
    process_rar_list()

评论

0赞 Paul Cornelius 12/8/2022
您可以为每个项目创建一个新的事件循环,这意味着不会进行基于异步的多任务处理。您仅将 asyncio 用作启动线程的低效方式。替换为 会得到相同的结果。可以将参数传递给没有 functools.partial 的线程。asyncio.new_event_loop().run_in_executor(...)threading.Thread(target=func).start()
0赞 Jaŭhieni Harochaŭ 12/9/2022
我发现为每个同步任务创建一个新线程比为许多同步任务使用一个线程(使用 asyncio.get_event_loop)要快得多。就像在简单的 time.wait() 函数上快几个数量级。无论如何,我们不能使用实际的协作多任务处理,因为有问题的函数在它们内部没有使用 await。
0赞 Paul Cornelius 12/9/2022
我相信你是对的,但这不是我的重点。您的程序运行并生成所需的行为,但效率非常低。您根本不需要使用 asyncio 来创建线程 - 只需使用线程模块中的方法即可。