NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #3051 most downloaded on PyPI
A robust implementation of concurrent.futures.ProcessPoolExecutor
Last release 5 days ago
29 Sep 2026
Release timing varies
gaps range from 4 weeks to 1.7 years
Most releases are documented
notes for 38 of 46 stable releases
Nothing withdrawn
no release was ever pulled
10 years old
47 releases · first in 2017
Fix cpu_count(only_physical_cores=True) to always take the number of physical cores into account, even when the usable CPU count is already restricted
Fix cpu_count(only_physical_cores=True) to always take the number of
physical cores into account, even when the usable CPU count is already
restricted by CPU affinity, Cgroup, or LOKY_MAX_CPU_COUNT. Previously,
the physical core count was ignored whenever another restriction already
applied. (#651)
Fix cpu_count(only_physical_cores=True) on Linux to always collapse
hyper-threading/SMT sibling logical CPUs reachable through the CPU affinity
mask (e.g. set via taskset). (#651)
Fix cpu_count(only_physical_cores=True) on Linux to identify physical
cores by their (socket, core id) pair instead of core id alone,
which could under-count physical cores on multi-socket machines where
core id is not unique across sockets. (#651)
Fix an unexpected error in the executor manager thread killing it silently,
which left every pending future unresolved so that waiting on a result hung
forever. A warning filter turning one of the warnings the thread emits into
an error was enough to trigger this. The executor is now flagged as broken
and the error is reported as the cause of the BrokenProcessPool raised
by the futures. (#641)
Fix shutdown(kill_workers=True) crashing the executor manager thread
with a KeyError when tasks were still queued, which skipped the cleanup
of the executor's queues and processes. (#641)
Fix an error while reporting a task that failed to be sent to the workers
killing the call queue feeder thread silently, which left every later task
unsent so that waiting on a result hung forever. The executor is now flagged
as broken and the error is reported as the cause of the BrokenProcessPool
raised by the futures. (#641)
Report a worker that is recycled because of a suspected memory leak with a message that says so, and only once per executor instead of once per restart. Such a restart used to repeatedly emit the generic "A worker stopped while some jobs were given to the executor" warning for the whole life of a long-running executor. (#641)
Add the LOKY_MAX_MEMORY_LEAK_SIZE environment variable to configure how
much memory growth is tolerated before a worker is recycled, previously
hardcoded to 300 MB. The reference it is compared against is measured after
the worker's first task and never updated, so a workload whose tasks differ
a lot in memory footprint can cross that threshold without leaking
anything. (#641)
get_reusable_executor() is now thread-local: each thread has its own
reusable executor. This means the API is now thread-safe. (#640)
One column per quarter.
Support detection of the number of physical cores in cpu_count(only_physical_cores=True) on FreeBSD.
Support detection of the number of physical cores in
cpu_count(only_physical_cores=True) on FreeBSD. (#457)
Fix cpu_count failing on certain OS due to empty
cpu.max file (#479)
Fix a race condition in get_reusable_executor where concurrent
submissions after executor replacement could raise
ShutdownExecutorError. (#632)
Fix ProcessPoolExecutor.shutdown(wait=True) hanging forever when the
only work items left are cancelled ones, as happens after abandoning an
Executor.map iterator or cancelling a submitted future. Ports the
upstream fix for https://github.com/python/cpython/issues/94440. (#653)
Fix the executor manager thread dying with InvalidStateError when a
cancelled work item is still pending as the pool breaks, which left the
remaining futures unresolved forever. Ports the upstream fix for
https://github.com/python/cpython/issues/107219. (#653)
Fix an exception raised by a worker being reported as a None result
instead of being raised, when the exception evaluates as falsey. Ports the
upstream fix for https://github.com/python/cpython/issues/132063. (#653)
Wait on the resource tracker's process handle instead of its pid on Windows,
avoiding intermittent PermissionError exceptions and hangs during
interpreter shutdown. (#472, original fix in #643)
Python 3.15 support. (#472)
Drop support for Python 3.9, as it is no longer receiving security updates. (#647)
Make cpu_count(only_physical=True) faster on Windows by using Windows C API
through ctypes. (#649)
Nothing published for this version
Fix resource_tracker compatibility with python 3.13.7+.
resource_tracker compatibility with python 3.13.7+. (#461)Fix resource_tracker teardown check for earlier python version.
resource_tracker teardown check for earlier python version. (#455)Fix call_queue size in the _ReusableExecutor, which could be too small when max_workers is larger than cpu_count().
call_queue size in the _ReusableExecutor, which could be too
small when max_workers is larger than cpu_count(). (#452)Fix resource_tracker teardown to accommodate with newer version of Python (3.12.10+, 3.13.3+, 3.14+).
resource_tracker teardown to accommodate with newer version of
Python (3.12.10+, 3.13.3+, 3.14+). (#450)Fix a regression to support Python 3.10 (and Python 3.14 dev) by passing version-specific allow_vfork and pgid_to_set arguments to _posixsubprocess.fo
allow_vfork and pgid_to_set arguments to
_posixsubprocess.fork_exec. (#445)Avoid raising DeprecationWarning related to os.fork when running in a natively multi-threaded process. (#429).
Avoid raising DeprecationWarning related to os.fork when running in a
natively multi-threaded process. (#429).
Fix a crash when calling commands that access stdin via subprocess.run in
worker processes on POSIX systems. (#429).
Automatically call faulthandler.enable() when starting loky worker
processes to report more informative information (post-mortem Python
tracebacks in particular) on worker crashs. (#419).
Fix a random deadlock caused by a race condition at executor shutdown that was observed on Linux and Windows. (#438)
Fix detection of the number of physical cores in
cpu_count(only_physical_cores=True) on some Linux systems and recent
Windows versions. (#425)
Drop support for Python 3.7 and Python 3.8. (#409)
Drop support for PyPy. (#427)
RELEASE loky 3.4.1 - bugfix release
RELEASE loky 3.4.1 - bugfix release
_MAX_WINDOWS_WORKERS constant. (#408)See CHANGES.md for a list of changes between releases.
See CHANGES.md for a list of changes between releases.
New Contributors: @glemaitre, @haim0n, @moinnadeem , @schlerp, @uniontech-lilinjie
Fix exception __cause__ not being propagated with
tblib.pickling_support.install(). (#255).
Fix handling of CPU affinity by using psutil's cpu_affinity on platforms
that do not implement os.sched_getaffinity, such as PyPy. (#381).
Make the executor's gc process more thread-safe, in particular for PyPy, where the gc calls can be run in any thread. (#384).
Fix crash when using max_workers > 61 on Windows. Loky will no longer
attempt to use more than 61 workers on that platform (or 60 depending on the
Python version). (#390).
Fix loky compat with python 3.11 for nested calls. (#394).
Adapt the cooldown strategy when shutting down an executor with full
call_queue. This should accelerate the time taken to shutdown
in general, in particular on overloaded machines. (#399).
Fix worker management logic in get_reusable_executor to ensure the number of started worker process actually correspond to max_workers when existing p
get_reusable_executor to ensure
the number of started worker process actually correspond to max_workers
when existing process concurrently time out (#370).Fix leaked processes and deadlock when the Python interpreter exits after a using nested calls to get_reusable_executor (#363).
Fix leaked processes and deadlock when the Python interpreter exits
after a using nested calls to get_reusable_executor (#363).
Fix an exception in the SemLock finalizer when the semaphore has been concurrently unlinked (#366).
Fix loky.cpu_count() to properly detect the number of allowed CPUs based on the /sys/fs/cgroup/cpu.max file on newest Linux versions with cgroup v2. F
Fix loky.cpu_count() to properly detect the number of allowed CPUs based on the /sys/fs/cgroup/cpu.max file on newest Linux versions with cgroup v2. Fall-back to the /sys/fs/cgroup/cpu/cpu.cfs_quota_us file to keep on supporting Linux versions that use cgroup v1 (#355 and #358).
Fix an exception that could be raised in an auxiliary thread when garbage collecting an executor instance when shutting down the the Python interpreter (#311).
Make shutdown(kill_workers=True) consistently use the SIGKILL
signal on POSIX. Previously a mix of SIGKILL and SIGTERM was issued
and could deadlock the shutdown process (#348 and #357).
Big code clean-up to drop support for older Python versions. Python 3.7 or later is now required. (#304)
Avoid a NameError when calling the exit builtin on Windows when loky is executed as part of a frozen Python binary.
Avoid a NameError when calling the exit builtin on Windows when
loky is executed as part of a frozen Python binary. (#290)
Make it possible to automatically trace workers when profiling with VizTracer (#299).
Fix a side-effect bug in the registration of custom reducers the loky subclass of cloudpickle.CloudPickler with cloudpickle 1.6.0. (#272).
Fix a side-effect bug in the registration of custom reducers the loky
subclass of cloudpickle.CloudPickler with cloudpickle 1.6.0. (#272).
Fix support for Python 3.9 and test against python-nightly from now on (#250).
Add a parameter to cpu_count, only_physical_cores, to return the
number of physical cores instead of the number of logical cores (#271).
Fix thread-safety issues when iterating over the list of processes (Dictionary changed sized during iteration) (#263).
Internal refactoring: add private factory class method to _ReusablePoolExecutor to ease extensibility in joblib (#253).
_ReusablePoolExecutor to ease extensibility in joblib (#253).Increase the residual memory increase threshold (100MB -> 300MB) used by loky for memory leak detection (causing loky workers to be shutdown/restarted
Increase the residual memory increase threshold (100MB -> 300MB) used by loky for memory leak detection (causing loky workers to be shutdown/restarted), in order to reduce the amount of false positives (#238).
In Python 3.8, loky processes now inherit multiprocessing's
resource_tracker created from their parent. As a consequence, no spurious
resource_tracker warnings are emitted when loky workers manipulate
shared_memory objects (#242).
Note that loky still needs to use its own resource tracker instance to manage
resources that require the reference counting logic such as joblib temporary
memory mapped files for now.
The resource_tracker now comes with built-in support for tracking files
in all OSes. In addition, Python processes can now signal they do not need a
shared resource anymore by using the
resource_tracker.maybe_unlink(resource_name, resource_type) method. After
all processes having access to the said resource have called this method, the
resource_tracker will proceed to unlink the resource. Previously, resource
unlinking by the resource_tracker was only done for leaked resources at
interpreter exit (#228).
Fix shutdown(wait=False) that was potentially leading to deadlocks and froze
interpreters (#246).
Backport ExecutorManagerThread from cpython to refactor
_queue_management_thread and ease maintenance (#246).
Copy the environment variables in the child process for LokyProcess. Also add a env argument in LokyProcess, ProcessPoolExecutor and get_reusable_exec
Copy the environment variables in the child process for LokyProcess. Also
add a env argument in LokyProcess, ProcessPoolExecutor and
get_reusable_executor to over-write consistently some environment variable
in the child process. This allows setting env variables before loading any
module.
Note: this feature is unreliable on Windows with Python < 3.6. (#217)
Fix a bug making all loky workers crash on Windows for Python>3.7 when using a virtual environment (#216).
Fix a bug of the resource_tracker that could create unlimited freeze on Windows
resource_tracker that could create unlimited freeze on
Windows (#212)Backport ResourceTracker from Python 3.8 concurrent.futures and fix tracker pid issue (#204 and #202).
Backport ResourceTracker from Python 3.8 concurrent.futures and fix tracker pid issue (#204 and #202).
Fix bug when pickling function with kw-only argument (#264).
Fix bug in pickler.dispatch_table handling that could cause a crash
with the new cloudpickle fast pickler under Python 3.8 (#203).
Fix a race condition that could cause a deadlock with PyPy (#191).
Fixed compat with python2.7 in semaphore tracker.
Fixed loky pickler in workers. (#184)
Fixed compat with python2.7 in semaphore tracker. (#186)
Fixed a bug when setting the cause of an exception without message under Python 2.7 (#179).
Default serialization is now done with cloudpickle.
Default serialization is now done with cloudpickle. (#178)
The base Pickler in loky can now be changed through the LOKY_PICKLER
variable or programmatically with set_loky_pickler. (#171)
Improve reporting of causes in python2.7 (#174)
Improve workers crash reporting by displaying the exitcodes of
workers in TerminatedWorkerError (#173)
Add a wrap_non_picklable_objects decorator in loky to make it
easy to fix serialization failure for nested functions defined in
the __main__ module. (#171)
Improve error reporting when a worker process is terminated abruptly (#169).
Improve error reporting when a worker process is terminated abruptly (#169).
Remove spurious debug output.
loky.cpu_count() is now upper-bounded by the value of the LOKY_MAX_CPU_COUNT environment variable (when defined).
Add support for PyPy3.
loky.cpu_count() is now upper-bounded by the value of the
LOKY_MAX_CPU_COUNT environment variable (when defined).
Fix issue #165 to make loky.cpu_count() return an integer under
Python 2.7 with fractional docker CPU usage quotas.
Add a set_start_method function in loky.backend.context. Note that now, loky does not respect the start method set using multiprocessing.set_start_met
set_start_method function in loky.backend.context. Note
that now, loky does not respect the start method set using
multiprocessing.set_start_method anymore. It is thus mandatory
to use the loky function to have the correct behavior.Fix pickling logic in loky. Now the serialization is consistent between initializer and tasks. Also fixes the logic behind the environment variable LO
Fix pickling logic in loky. Now the serialization is consistent
between initializer and tasks. Also fixes the logic behind the
environment variable LOKY_PICKLER.
Improve reporting for tasks unpickling errors.
Fix deadlock when large objects are sent to workers.
Fix context and start_method logic for loky contexts.
Add a protection against memory-leaks for long running worker processes: if the memory usage has increased by more than 100 MB (after a garbage collec
Add a protection against memory-leaks for long running worker processes: if the memory usage has increased by more than 100 MB (after a garbage collection), the worker is automatically restarted before accepting new tasks. This protection is only active when psutil is installed.
psutil is now a soft-dependency of loky: it is used to recursively terminate children processes when available but there is a fallback for windows and all unices with pgrep installed otherwise.
Fix win32 failure to kill worker process with taskkill returning 255
Fix bad interaction between max_workers=None and reuse='auto' (#132).
max_workers=None and reuse='auto' (#132).get_reusable_executor (#134)Fix terminate for nested processes
Fix queue size in reusable executor
Add documentation, accessible on http://loky.readthedocs.io
ReusablePoolExecutor._resize and ProcessPoolExecutor.shutdown.Nothing published for this version
Fix handling of Full Queue exception at shutdown time. (#107).
Fix a potential deadlock when shutting down a past reusable executor instance with to create a new instance with different parameters. (#101, #102)
Nothing published for this version
Fix crash for 64-bit Python under Windows.
Nothing published for this version
Fix shutdown with exit at pickle deadlock
Fix default backend for ReusablePoolExecutor
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →