提问人:jhown 提问时间:12/8/2022 更新时间:12/8/2022 访问量:89
异步遍历两个列表?
traverse two lists asynchronously?
问:
我有两个列表,lzma2_list 和 rar_list。两者都具有随机数量的对象名称,这些名称每天都在变化。这些对象所在的目录名为“O:”,有 2 种方法可以处理此数据。
bkp.zipto_rar(path,object_name)
bkp.zipto_lzma(path,object_name)
如何在不等待一个项目完成的情况下异步获取列表中的所有项目?
使用异步列表和线程加速压缩 我尝试使用这个问题的答案,但在我的情况下,这些方法接收 2 个参数,一个是固定的,指的是目录,另一个会不断变化,指的是列表中的项目。
答:
0赞
Jaŭhieni Harochaŭ
12/8/2022
#1
由于函数采用参数,因此应使用参数将其转换为不带参数的签名。functools.partial
然后,如果函数受 IO 限制,则可以用于处理后台线程中的每个项目,或者如果函数受 CPU 限制,则可以用于处理后台进程中的项目。asyncio.new_event_loop().run_in_executor
multiprocessing.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 来创建线程 - 只需使用线程模块中的方法即可。
评论
bkp.zipto_rar
bkp.zipto_lzma