import concurrent.futures import tempfile import os import shutil import subprocess import platform import sys def task(kind): dirname = tempfile.mkdtemp() with open(os.path.join(dirname, "stdout.txt"), "w") as f_w: if kind == "subprocess_devnull": with subprocess.Popen("dir", shell=True, stdout=subprocess.DEVNULL): pass elif kind == "subprocess_noredirect": with subprocess.Popen("dir > NUL", shell=True): pass elif kind == "subprocess_redirfile": with subprocess.Popen("dir", shell=True, stdout=f_w): pass elif kind == "nosubprocess": print("Starting", file=f_w) import time time.sleep(0.1) print("Stop", file=f_w) else: raise ValueError("invalid value {}".format(kind)) shutil.rmtree(dirname) def execute_tasks(N, parallel, kind): results = [] def task_done(f): if f.exception() is None: results.append(True) else: #print(f.exception()) results.append(f.exception()) threadpool = concurrent.futures.ThreadPoolExecutor(max_workers=parallel) for i in range(N): threadpool.submit(task, kind).add_done_callback(task_done) threadpool.shutdown() errors = [r for r in results if r is not True] print(FMTSTRING.format(kind, parallel, "OK" if len(errors) == 0 else "{} errors (of {})".format(len(errors), N))) N = 20 print("Version:", sys.version) print("Platform:", platform.platform()) print("Tasks:", N) print() FMTSTRING = "{:25} {:<10} {:10}" print(FMTSTRING.format(*"task_type #threads result".split())) execute_tasks(N, 5, "subprocess_redirfile") execute_tasks(N, 1, "subprocess_redirfile") execute_tasks(N, 5, "subprocess_devnull") execute_tasks(N, 1, "subprocess_devnull") execute_tasks(N, 5, "subprocess_noredirect") execute_tasks(N, 1, "subprocess_noredirect") execute_tasks(N, 5, "nosubprocess") execute_tasks(N, 1, "nosubprocess")