来自函数sync_lister()
的控制台输出:
20203.161 ms
19930.7166 ms
21279.1429 ms
18988.5079 ms
17724.5125 ms
11358.8549 ms
36164.6077 ms
20183.306099999998 ms
14238.174599999998 ms
20383.551 ms
Process finished with exit code 0
很好,这就是我的期望。现在我想把它放在一个工作池中,并以大约4倍的速度完成它。
我以为我做得恰到好处。为什么我没有任何输出?
运行async_lister()
时没有控制台输出,应用程序立即返回。
完整的代码如下。如果您需要ffprobe
包装器或其他任何内容的来源,请告诉我。
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import os
from utilities import glob_from
from controller import run_ffprobe
from multiprocessing import Pool
INPUT_DIR = "C:/Users/spike/Music/Deezloader"
def get_duration(metadata):
return float(metadata.get("format", {}).get("duration", 0)) * 100
def example_callback(metadata):
print(get_duration(metadata), "ms")
args_list = [(os.path.join(INPUT_DIR, path),) for path in glob_from(INPUT_DIR, "flac")[0:10]]
# Example: [('C:/Users/spike/Music/Deezloader\\AWOLNATION - Handyman\\1 - AWOLNATION - Handyman.flac',), ...]
def sync_lister():
for args in args_list:
example_callback(run_ffprobe(*args))
def async_lister():
pool = Pool(4) # Creates four threads, four items from "args" will be run with "run_ffprobe" at a time
pool.apply_async(run_ffprobe, args=args_list, callback=example_callback)
# Set the target to "run_ffprobe", and each item in "args_list" will be unpacked as arguments
# and sent to that function when a pool worker is free
pool.close() # Close the pool, no more process can be added
pool.join() # Wait for all of the processes to complete
if __name__ == "__main__":
sync_lister() # Working
async_lister() # Not working
答案 0 :(得分:1)
正如apply()
/apply_async()
documentation中所述,每次调用apply()
或apply_async()
都相当于一次调用您传递的函数作为第一个参数(即run_ffprobe
)。
在同步代码中,您将args_list
的每个元素传递给单独的run_ffprobe()
来电:
for args in args_list:
example_callback(run_ffprobe(*args))
在您的异步代码中,您要求池计算:
example_callback(run_ffprobe(args_list))
这不是你想要它做的。您需要在循环中调用apply_async()
,就像您在循环中调用run_ffprobe()
一样。或者,您可以使用map_async()
,但这只会使用整个结果列表调用一次回调。这似乎与您在同步代码中所做的不相符,但您可以重写回调以适应此模式,或使用functools.partial(map, example_callback)
之类的内容作为map_async()
的回调。