我有以下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
答案 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!")