Skip to content

Commit f867711

Browse files
miss-islingtonYvesDupgpshead
authored
[3.13] gh-132898: Add a note in multiprocessing.Process docs about creating a process in a REPL (GH-137118) (#137155)
gh-132898: Add a note in `multiprocessing.Process` docs about creating a process in a REPL (GH-137118) * Reword, expand, and clarify the limitation, highlighting the REPL case. * Mention in the high level Process description. * added a pointer to the GH issue from the doc note --------- (cherry picked from commit 4e40f2b) Co-authored-by: Duprat <yduprat@gmail.com> Co-authored-by: Gregory P. Smith <greg@krypto.org>
1 parent 81079d7 commit f867711

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

Doc/library/concurrent.futures.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ that :class:`ProcessPoolExecutor` will not work in the interactive interpreter.
243243
Calling :class:`Executor` or :class:`Future` methods from a callable submitted
244244
to a :class:`ProcessPoolExecutor` will result in deadlock.
245245

246+
Note that the restrictions on functions and arguments needing to picklable as
247+
per :class:`multiprocessing.Process` apply when using :meth:`~Executor.submit`
248+
and :meth:`~Executor.map` on a :class:`ProcessPoolExecutor`. A function defined
249+
in a REPL or a lambda should not be expected to work.
250+
246251
.. class:: ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=(), max_tasks_per_child=None)
247252

248253
An :class:`Executor` subclass that executes calls asynchronously using a pool

Doc/library/multiprocessing.rst

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ To show the individual process IDs involved, here is an expanded example::
9797
For an explanation of why the ``if __name__ == '__main__'`` part is
9898
necessary, see :ref:`multiprocessing-programming`.
9999

100+
The arguments to :class:`Process` usually need to be unpickleable from within
101+
the child process. If you tried typing the above example directly into a REPL it
102+
could lead to an :exc:`AttributeError` in the child process trying to locate the
103+
*f* function in the ``__main__`` module.
100104

101105

102106
.. _multiprocessing-start-methods:
@@ -218,9 +222,12 @@ processes for a different context. In particular, locks created using
218222
the *fork* context cannot be passed to processes started using the
219223
*spawn* or *forkserver* start methods.
220224

221-
A library which wants to use a particular start method should probably
222-
use :func:`get_context` to avoid interfering with the choice of the
223-
library user.
225+
Libraries using :mod:`multiprocessing` or
226+
:class:`~concurrent.futures.ProcessPoolExecutor` should be designed to allow
227+
their users to provide their own multiprocessing context. Using a specific
228+
context of your own within a library can lead to incompatibilities with the
229+
rest of the library user's application. Always document if your library
230+
requires a specific start method.
224231

225232
.. warning::
226233

@@ -518,9 +525,42 @@ The :mod:`multiprocessing` package mostly replicates the API of the
518525
to pass to *target*.
519526

520527
If a subclass overrides the constructor, it must make sure it invokes the
521-
base class constructor (:meth:`Process.__init__`) before doing anything else
528+
base class constructor (``super().__init__()``) before doing anything else
522529
to the process.
523530

531+
.. note::
532+
533+
In general, all arguments to :class:`Process` must be picklable. This is
534+
frequently observed when trying to create a :class:`Process` or use a
535+
:class:`concurrent.futures.ProcessPoolExecutor` from a REPL with a
536+
locally defined *target* function.
537+
538+
Passing a callable object defined in the current REPL session causes the
539+
child process to die via an uncaught :exc:`AttributeError` exception when
540+
starting as *target* must have been defined within an importable module
541+
in order to be loaded during unpickling.
542+
543+
Example of this uncatchable error from the child::
544+
545+
>>> import multiprocessing as mp
546+
>>> def knigit():
547+
... print("Ni!")
548+
...
549+
>>> process = mp.Process(target=knigit)
550+
>>> process.start()
551+
>>> Traceback (most recent call last):
552+
File ".../multiprocessing/spawn.py", line ..., in spawn_main
553+
File ".../multiprocessing/spawn.py", line ..., in _main
554+
AttributeError: module '__main__' has no attribute 'knigit'
555+
>>> process
556+
<SpawnProcess name='SpawnProcess-1' pid=379473 parent=378707 stopped exitcode=1>
557+
558+
See :ref:`multiprocessing-programming-spawn`. While this restriction is
559+
not true if using the ``"fork"`` start method, as of Python ``3.14`` that
560+
is no longer the default on any platform. See
561+
:ref:`multiprocessing-start-methods`.
562+
See also :gh:`132898`.
563+
524564
.. versionchanged:: 3.3
525565
Added the *daemon* parameter.
526566

@@ -2993,10 +3033,10 @@ start method.
29933033

29943034
More picklability
29953035

2996-
Ensure that all arguments to :meth:`Process.__init__` are picklable.
2997-
Also, if you subclass :class:`~multiprocessing.Process` then make sure that
2998-
instances will be picklable when the :meth:`Process.start
2999-
<multiprocessing.Process.start>` method is called.
3036+
Ensure that all arguments to :class:`~multiprocessing.Process` are
3037+
picklable. Also, if you subclass ``Process.__init__``, you must make sure
3038+
that instances will be picklable when the
3039+
:meth:`Process.start <multiprocessing.Process.start>` method is called.
30003040

30013041
Global variables
30023042

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy