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)