title: Python ThreadPoolExecutor - is the callback guaranteed to run in the same thread as submitted func?
body: <p>In the ThreadPoolExecutor (TPE), is the callback always guaranteed to run in the same thread as the submitted function? </p>
  
  <p>For example, I tested this with the following code. I ran it many times and it seemed like <code>func</code> and <code>callback</code> always ran in the same thread. </p>
  
  <pre><code>import concurrent.futures 
  import random 
  import threading 
  import time 
  
  executor = concurrent.futures.ThreadPoolExecutor(max_workers=3) 
  
  def func(x): 
      time.sleep(random.random()) 
      return threading.current_thread().name 
  
  def callback(future): 
      time.sleep(random.random()) 
      x = future.result() 
      cur_thread = threading.current_thread().name 
      if (cur_thread != x): 
          print(cur_thread, x) 
  
  print('main thread: %s' % threading.current_thread()) 
  for i in range(10000): 
      future = executor.submit(func, i) 
      future.add_done_callback(callback) 
  </code></pre>
  
  <p>However, it seemed to fail when I removed the <code>time.sleep(random.random())</code> statements, i.e. at least a few <code>func</code> functions and <code>callbacks</code> <strong>did not</strong> run in the same thread. </p>
  
  <p>For a project that I am working on, the callback must always run on the same thread as the submitted function, so I wanted to be sure that this is guaranteed by TPE. (And also the results of the test without the random sleep seemed puzzling). </p>
  
  <p>I looked at the <a href="https://hg.python.org/cpython/file/6d44906344f4/Lib/concurrent/futures/_base.py#l297" rel="noreferrer">source code for executors</a> and it does not seem like we switch the thread to the main thread before we run the callback. But just wanted to be sure. </p>