# HG changeset patch # User Augie Fackler # Date 1470061908 14400 # Mon Aug 01 10:31:48 2016 -0400 # Node ID 62e0918e62454d03a337b9de7288f235dd1a5b17 # Parent 6c2e2de5ab8e8276b6daea3c601c89024bc9fa20 concurrent.futures.ThreadPoolExecutor: add support for naming threads This is sometimes useful when binaries contain many thread pools, as it's now possible to figure out what category of thread is stuck. diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -81,7 +81,7 @@ def _worker(executor_reference, work_que _base.LOGGER.critical('Exception in worker', exc_info=True) class ThreadPoolExecutor(_base.Executor): - def __init__(self, max_workers=None): + def __init__(self, max_workers=None, thread_name_prefix=None): """Initializes a new ThreadPoolExecutor instance. Args: @@ -100,6 +100,7 @@ class ThreadPoolExecutor(_base.Executor) self._threads = set() self._shutdown = False self._shutdown_lock = threading.Lock() + self._thread_name_prefix = thread_name_prefix def submit(self, fn, *args, **kwargs): with self._shutdown_lock: @@ -122,7 +123,11 @@ class ThreadPoolExecutor(_base.Executor) # TODO(bquinlan): Should avoid creating new threads if there are more # idle threads than items in the work queue. if len(self._threads) < self._max_workers: - t = threading.Thread(target=_worker, + if self._thread_name_prefix: + name = self._thread_name_prefix + '_%d' % len(self._threads) + else: + name = None + t = threading.Thread(name=name, target=_worker, args=(weakref.ref(self, weakref_cb), self._work_queue)) t.daemon = True diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -154,6 +154,17 @@ class ThreadPoolShutdownTest(ThreadPoolM for t in threads: t.join() + def test_thread_names(self): + executor = futures.ThreadPoolExecutor( + max_workers=5, thread_name_prefix='SpecialPool') + executor.map(abs, range(-5, 5)) + threads = executor._threads + del executor + + for t in threads: + self.assertRegex(t.name, '^SpecialPool_[0-4]$') + t.join() + class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest, unittest.TestCase): def _prime_executor(self):