diff options
author | Brian Quinlan <brian@sweetapp.com> | 2011-04-07 22:19:33 (GMT) |
---|---|---|
committer | Brian Quinlan <brian@sweetapp.com> | 2011-04-07 22:19:33 (GMT) |
commit | f007876bd64def2829a242e0cf5adfd3ef25c4be (patch) | |
tree | 1ec073f7cf806fa500a9146363e56686f90497aa /Lib | |
parent | 0df80926c93ac71b032fffa215cf7b2f831d81b6 (diff) | |
download | cpython-f007876bd64def2829a242e0cf5adfd3ef25c4be.zip cpython-f007876bd64def2829a242e0cf5adfd3ef25c4be.tar.gz cpython-f007876bd64def2829a242e0cf5adfd3ef25c4be.tar.bz2 |
Issue #11777: Executor.map does not submit futures until iter.next() is called
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/concurrent/futures/_base.py | 22 | ||||
-rw-r--r-- | Lib/test/test_concurrent_futures.py | 10 |
2 files changed, 22 insertions, 10 deletions
diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index 79b91d4..6cfded3 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -536,15 +536,19 @@ class Executor(object): fs = [self.submit(fn, *args) for args in zip(*iterables)] - try: - for future in fs: - if timeout is None: - yield future.result() - else: - yield future.result(end_time - time.time()) - finally: - for future in fs: - future.cancel() + # Yield must be hidden in closure so that the futures are submitted + # before the first iterator value is required. + def result_iterator(): + try: + for future in fs: + if timeout is None: + yield future.result() + else: + yield future.result(end_time - time.time()) + finally: + for future in fs: + future.cancel() + return result_iterator() def shutdown(self, wait=True): """Clean-up the resources associated with the Executor. diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 2662af7..ec84a66 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -369,7 +369,15 @@ class ExecutorTest(unittest.TestCase): class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest): - pass + def test_map_submits_without_iteration(self): + """Tests verifying issue 11777.""" + finished = [] + def record_finished(n): + finished.append(n) + + self.executor.map(record_finished, range(10)) + self.executor.shutdown(wait=True) + self.assertCountEqual(finished, range(10)) class ProcessPoolExecutorTest(ProcessPoolMixin, ExecutorTest): |