Python: concurrent.futures How to make it cancelable?

后端 未结 3 1951
-上瘾入骨i
-上瘾入骨i 2020-12-03 13:50

Python concurrent.futures and ProcessPoolExecutor provide a neat interface to schedule and monitor tasks. Futures even provide a .cancel() method:

3条回答
  •  無奈伤痛
    2020-12-03 14:41

    I don't know why concurrent.futures.Future does not have a .kill() method, but you can accomplish what you want by shutting down the process pool with pool.shutdown(wait=False), and killing the remaining child processes by hand.

    Create a function for killing child processes:

    import signal, psutil
    
    def kill_child_processes(parent_pid, sig=signal.SIGTERM):
        try:
            parent = psutil.Process(parent_pid)
        except psutil.NoSuchProcess:
            return
        children = parent.children(recursive=True)
        for process in children:
            process.send_signal(sig)
    

    Run your code until you get the first result, then kill all remaining child processes:

    from concurrent.futures import ProcessPoolExecutor, FIRST_COMPLETED, wait
    
    # function that profits from partitioned search space
    def m_run(partition):
        for elem in partition:
            if elem == 135135515:
                return elem
        return False
    
    futures = []
    # used to create the partitions
    steps = 100000000
    pool = ProcessPoolExecutor(max_workers=4)
    for i in range(4):
        # run 4 tasks with a partition, but only *one* solution is needed
        partition = range(i*steps,(i+1)*steps)
        futures.append(pool.submit(m_run, partition))
    
    done, not_done = wait(futures, timeout=3600, return_when=FIRST_COMPLETED)
    
    # Shut down pool
    pool.shutdown(wait=False)
    
    # Kill remaining child processes
    kill_child_processes(os.getpid())
    

提交回复
热议问题