Python的`ThreadPoolExecutor`不使用执行程序的数量

时间:2018-06-25 14:06:30

标签: python python-multithreading threadpoolexecutor

我有以下Python代码:

import sys
import os
from concurrent.futures import ThreadPoolExecutor

VIDEOS = [   # A list of 9 videos
    {... bla bla ...},
    {... bla bla ...},
    {... bla bla ...}
]

SAMPLING_FREQUENCIES = [1, 2.4, 3.71, ... , 14.3] # A list of 8 frequencies

def process_video(video_obj, sampling_frequency, process_work_dir):
    os.makedirs(process_work_dir)
    # ... do some heavy processing ...

if __name__ == '__main__':
    output_work_dir = sys.argv[1]
    os.makedirs(output_work_dir)
    executor = ThreadPoolExecutor(max_workers=4)
    for video_obj in VIDEOS:
        for samp_fps in SAMPLING_FREQUENCIES:  # Totally 8 * 9 threads should be waiting to be executed
            work_dir = os.path.join(output_work_dir, os.path.basename(video_obj['path']), str(samp_fps))            
            executor.submit(lambda : process_video(video_obj, samp_fps, work_dir))

我观察到的是,首先,正如预期的那样,正在运行4个线程。我可以通过确保恰好创建了4个工作目录来对其进行验证。

然后,第一个线程完成其工作,并且按预期,另一个正在等待的线程开始运行。

问题是,尽管我创建了72个线程(9个视频乘以8个采样频率),但是没有线程被执行。当第5个线程完成工作时,应用程序终止。

是错误,还是在了解ThreadPoolExecutor API时遇到问题?

我使用Python 3.6.5

1 个答案:

答案 0 :(得分:1)

如果您要执行者完成所有任务,则可能需要在with块中声明它。在这里,我添加的打印语句将在所有线程完成后打印出来。

您看到的问题是执行程序将提交内容而不是等待,从而使您的代码在遇到EOF终止执行解释程序关闭的杀死任务时死亡。
*不是这种情况,请忽略

也请注意这一行:
executor.submit(lambda : process_video(video_obj, samp_fps, work_dir)) lambda似乎是process_video方法的结果,这意味着它将在主线程中运行。我认为,如果按照文档中的建议进行指定,用法会更清晰,更干净。
executor.submit(process_video, video_obj, samp_fps, work_dir)

尝试一下:

if __name__ == '__main__':
    output_work_dir = sys.argv[1]
    os.makedirs(output_work_dir)
    with ThreadPoolExecutor(max_workers=4) as executor:
        for video_obj in VIDEOS:
            for samp_fps in SAMPLING_FREQUENCIES:  # Totally 8 * 9 threads should be waiting to be executed
                work_dir = os.path.join(output_work_dir, os.path.basename(video_obj['path']), str(samp_fps))            
                executor.submit(process_video, video_obj, samp_fps, work_dir)
    print("Hello, all done with thread work!")