title: Python: concurrent.futures How to make it cancelable?
body: <p>Python concurrent.futures and ProcessPoolExecutor provide a neat interface to schedule and monitor tasks. Futures even <a href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Future" rel="noreferrer">provide</a> a .cancel() method:</p>
  
  <blockquote>
    <p><strong>cancel()</strong>:    Attempt to cancel the call. If the call is <strong>currently being executed and cannot be cancelled</strong> then the method will return False, otherwise the call will be cancelled and the method will return True.</p>
  </blockquote>
  
  <p>Unfortunately in a simmilar <a href="https://stackoverflow.com/questions/26413613/asyncio-is-it-possible-to-cancel-a-future-been-run-by-an-executor">question</a> (concerning asyncio) the answer claims running tasks are uncancelable using this snipped of the documentation, but the docs dont say that, only if they are running AND uncancelable.</p>
  
  <p>Submitting multiprocessing.Events to the processes is also not trivially possible (doing so via parameters as in multiprocess.Process returns a RuntimeError) </p>
  
  <p>What am I trying to do? I would like to partition a search space and run a task for every partition. But it is enough to have ONE solution and the process is CPU intensive. So is there an actual comfortable way to accomplish this that does not offset the gains by using ProcessPool to begin with?</p>
  
  <p>Example:</p>
  
  <pre><code>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
  with ProcessPoolExecutor(max_workers=4) as pool:
      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, return_when=FIRST_COMPLETED)
      for d in done:
          print(d.result())
  
      print("---")
      for d in not_done:
          # will return false for Cancel and Result for all futures
          print("Cancel: "+str(d.cancel()))
          print("Result: "+str(d.result()))
  </code></pre>