Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
warn from concurrent.futures, reword things.
  • Loading branch information
gpshead committed Dec 31, 2022
commit e45fab669e5fcf8ac797c640224eb3768381a88c
19 changes: 16 additions & 3 deletions Lib/concurrent/futures/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,9 +616,9 @@ def __init__(self, max_workers=None, mp_context=None,
max_workers: The maximum number of processes that can be used to
execute the given calls. If None or not given then as many
worker processes will be created as the machine has processors.
mp_context: A multiprocessing context to launch the workers. This
object should provide SimpleQueue, Queue and Process. Useful
to allow specific multiprocessing start methods.
mp_context: A multiprocessing context to launch the workers created
using the multiprocessing.get_context('start method') API. This
object should provide SimpleQueue, Queue and Process.
initializer: A callable used to initialize worker processes.
initargs: A tuple of arguments to pass to the initializer.
max_tasks_per_child: The maximum number of tasks a worker process
Expand Down Expand Up @@ -650,6 +650,19 @@ def __init__(self, max_workers=None, mp_context=None,
mp_context = mp.get_context("spawn")
else:
mp_context = mp.get_context()
if (getattr(mp_context, "get_start_method", lambda: None)() == "fork"
and mp_context == mp.context._default_context._default_context):
import warnings
warnings.warn(
"The multiprocessing 'fork' start method will change "
"away from 'fork' in Python >= 3.14, per GH-84559. "
"concurrent.futures.process is built upon multiprocessing. "
"If your application requires continued use of 'fork', "
"pass a mp_context= parameter created with the start method "
"explicitly specified.",
category=mp.context.DefaultForkDeprecationWarning,
stacklevel=2,
)
self._mp_context = mp_context

# https://github.com/python/cpython/issues/90622
Expand Down
22 changes: 10 additions & 12 deletions Lib/multiprocessing/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class TimeoutError(ProcessError):
class AuthenticationError(ProcessError):
pass

class DefaultsDeprecationWarning(DeprecationWarning):
class DefaultForkDeprecationWarning(DeprecationWarning):
pass

#
Expand Down Expand Up @@ -261,6 +261,7 @@ def get_start_method(self, allow_none=False):
return self._actual_context._name

def get_all_start_methods(self):
"""Returns a list of the supported start methods, default first."""
if sys.platform == 'win32':
return ['spawn']
else:
Expand All @@ -284,19 +285,16 @@ def _Popen(process_obj):
return Popen(process_obj)

class _DeprecatedForkProcess(ForkProcess):
@classmethod
def _warn(cls, stacklevel):
@staticmethod
def _warn(stacklevel):
import warnings
warnings.warn(
"Use of the multiprocessing 'fork' start method by default is "
"deprecated. "
"The default will change in Python >= 3.14, per GH-84559. "
"Please use an explicit multiprocessing.get_context or "
"multiprocessing.set_start_method API call to specify your "
"application's start method if you want to use 'fork'."
" The 'spawn' and 'forkserver' start methods are safer "
"depending on the platform and application.",
category=DefaultsDeprecationWarning,
"The multiprocessing 'fork' start method will change "
"change away from 'fork' in Python >= 3.14, per GH-84559. "
"Use a multiprocessing.get_context(X) context or "
"call multiprocessing.set_start_method(X) to explicitly "
"specify your application's need if you really want 'fork'.",
category=DefaultForkDeprecationWarning,
stacklevel=stacklevel,
)

Expand Down
16 changes: 8 additions & 8 deletions Lib/test/test_multiprocessing_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from inspect import currentframe, getframeinfo
import multiprocessing
from multiprocessing.context import DefaultsDeprecationWarning
from multiprocessing.context import DefaultForkDeprecationWarning
import sys
from test.support import threading_helper
import unittest
Expand All @@ -29,35 +29,35 @@ def setUp(self):
def test_default_fork_start_method_warning_process(self):
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter('ignore')
warnings.filterwarnings('always', category=DefaultsDeprecationWarning)
warnings.filterwarnings('always', category=DefaultForkDeprecationWarning)
process = multiprocessing.Process(target=do_nothing)
process.start() # warning should point here.
join_process(process)
self.assertIsInstance(ws[0].message, DefaultsDeprecationWarning)
self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning)
self.assertIn(__file__, ws[0].filename)
self.assertEqual(getframeinfo(currentframe()).lineno-4, ws[0].lineno)
self.assertIn("'fork'", str(ws[0].message))
self.assertIn("start_method API", str(ws[0].message))
self.assertIn("get_context", str(ws[0].message))
self.assertEqual(len(ws), 1, msg=[str(x) for x in ws])

def test_default_fork_start_method_warning_pool(self):
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter('ignore')
warnings.filterwarnings('always', category=DefaultsDeprecationWarning)
warnings.filterwarnings('always', category=DefaultForkDeprecationWarning)
pool = multiprocessing.Pool(1) # warning should point here.
pool.terminate()
pool.join()
self.assertIsInstance(ws[0].message, DefaultsDeprecationWarning)
self.assertIsInstance(ws[0].message, DefaultForkDeprecationWarning)
self.assertIn(__file__, ws[0].filename)
self.assertEqual(getframeinfo(currentframe()).lineno-5, ws[0].lineno)
self.assertIn("'fork'", str(ws[0].message))
self.assertIn("start_method API", str(ws[0].message))
self.assertIn("get_context", str(ws[0].message))
self.assertEqual(len(ws), 1, msg=[str(x) for x in ws])

def test_no_mp_warning_when_using_explicit_fork_context(self):
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter('ignore')
warnings.filterwarnings('always', category=DefaultsDeprecationWarning)
warnings.filterwarnings('always', category=DefaultForkDeprecationWarning)
fork_mp = multiprocessing.get_context('fork')
pool = fork_mp.Pool(1)
pool.terminate()
Expand Down