mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
bpo-45735: Promise the long-time truth that args=list
works (GH-30982)
For threads, and for multiprocessing, it's always been the case that ``args=list`` works fine when passed to ``Process()`` or ``Thread()``, and such code is common in the wild. But, according to the docs, only a tuple can be used. This brings the docs into synch with reality. Doc changes by Charlie Zhao. Co-authored-by: Tim Peters <tim.peters@gmail.com>
This commit is contained in:
parent
5ab745fc51
commit
e466faa9df
6 changed files with 82 additions and 3 deletions
|
@ -485,7 +485,9 @@ The :mod:`multiprocessing` package mostly replicates the API of the
|
||||||
to ``True`` or ``False``. If ``None`` (the default), this flag will be
|
to ``True`` or ``False``. If ``None`` (the default), this flag will be
|
||||||
inherited from the creating process.
|
inherited from the creating process.
|
||||||
|
|
||||||
By default, no arguments are passed to *target*.
|
By default, no arguments are passed to *target*. The *args* argument,
|
||||||
|
which defaults to ``()``, can be used to specify a list or tuple of the arguments
|
||||||
|
to pass to *target*.
|
||||||
|
|
||||||
If a subclass overrides the constructor, it must make sure it invokes the
|
If a subclass overrides the constructor, it must make sure it invokes the
|
||||||
base class constructor (:meth:`Process.__init__`) before doing anything else
|
base class constructor (:meth:`Process.__init__`) before doing anything else
|
||||||
|
@ -503,6 +505,19 @@ The :mod:`multiprocessing` package mostly replicates the API of the
|
||||||
the target argument, if any, with sequential and keyword arguments taken
|
the target argument, if any, with sequential and keyword arguments taken
|
||||||
from the *args* and *kwargs* arguments, respectively.
|
from the *args* and *kwargs* arguments, respectively.
|
||||||
|
|
||||||
|
Using a list or tuple as the *args* argument passed to :class:`Process`
|
||||||
|
achieves the same effect.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
>>> from multiprocessing import Process
|
||||||
|
>>> p = Process(target=print, args=[1])
|
||||||
|
>>> p.run()
|
||||||
|
1
|
||||||
|
>>> p = Process(target=print, args=(1,))
|
||||||
|
>>> p.run()
|
||||||
|
1
|
||||||
|
|
||||||
.. method:: start()
|
.. method:: start()
|
||||||
|
|
||||||
Start the process's activity.
|
Start the process's activity.
|
||||||
|
|
|
@ -314,7 +314,7 @@ since it is impossible to detect the termination of alien threads.
|
||||||
or "Thread-*N* (target)" where "target" is ``target.__name__`` if the
|
or "Thread-*N* (target)" where "target" is ``target.__name__`` if the
|
||||||
*target* argument is specified.
|
*target* argument is specified.
|
||||||
|
|
||||||
*args* is the argument tuple for the target invocation. Defaults to ``()``.
|
*args* is a list or tuple of arguments for the target invocation. Defaults to ``()``.
|
||||||
|
|
||||||
*kwargs* is a dictionary of keyword arguments for the target invocation.
|
*kwargs* is a dictionary of keyword arguments for the target invocation.
|
||||||
Defaults to ``{}``.
|
Defaults to ``{}``.
|
||||||
|
@ -353,6 +353,19 @@ since it is impossible to detect the termination of alien threads.
|
||||||
the *target* argument, if any, with positional and keyword arguments taken
|
the *target* argument, if any, with positional and keyword arguments taken
|
||||||
from the *args* and *kwargs* arguments, respectively.
|
from the *args* and *kwargs* arguments, respectively.
|
||||||
|
|
||||||
|
Using list or tuple as the *args* argument which passed to the :class:`Thread`
|
||||||
|
could achieve the same effect.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
>>> from threading import Thread
|
||||||
|
>>> t = Thread(target=print, args=[1])
|
||||||
|
>>> t.run()
|
||||||
|
1
|
||||||
|
>>> t = Thread(target=print, args=(1,))
|
||||||
|
>>> t.run()
|
||||||
|
1
|
||||||
|
|
||||||
.. method:: join(timeout=None)
|
.. method:: join(timeout=None)
|
||||||
|
|
||||||
Wait until the thread terminates. This blocks the calling thread until
|
Wait until the thread terminates. This blocks the calling thread until
|
||||||
|
|
|
@ -247,6 +247,30 @@ class _TestProcess(BaseTestCase):
|
||||||
self.assertEqual(current.ident, os.getpid())
|
self.assertEqual(current.ident, os.getpid())
|
||||||
self.assertEqual(current.exitcode, None)
|
self.assertEqual(current.exitcode, None)
|
||||||
|
|
||||||
|
def test_args_argument(self):
|
||||||
|
# bpo-45735: Using list or tuple as *args* in constructor could
|
||||||
|
# achieve the same effect.
|
||||||
|
args_cases = (1, "str", [1], (1,))
|
||||||
|
args_types = (list, tuple)
|
||||||
|
|
||||||
|
test_cases = itertools.product(args_cases, args_types)
|
||||||
|
|
||||||
|
for args, args_type in test_cases:
|
||||||
|
with self.subTest(args=args, args_type=args_type):
|
||||||
|
q = self.Queue(1)
|
||||||
|
# pass a tuple or list as args
|
||||||
|
p = self.Process(target=self._test_args, args=args_type((q, args)))
|
||||||
|
p.daemon = True
|
||||||
|
p.start()
|
||||||
|
child_args = q.get()
|
||||||
|
self.assertEqual(child_args, args)
|
||||||
|
p.join()
|
||||||
|
close_queue(q)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _test_args(cls, q, arg):
|
||||||
|
q.put(arg)
|
||||||
|
|
||||||
def test_daemon_argument(self):
|
def test_daemon_argument(self):
|
||||||
if self.TYPE == "threads":
|
if self.TYPE == "threads":
|
||||||
self.skipTest('test not appropriate for {}'.format(self.TYPE))
|
self.skipTest('test not appropriate for {}'.format(self.TYPE))
|
||||||
|
|
|
@ -123,6 +123,32 @@ class ThreadTests(BaseTestCase):
|
||||||
thread = threading.Thread(target=func)
|
thread = threading.Thread(target=func)
|
||||||
self.assertEqual(thread.name, "Thread-5 (func)")
|
self.assertEqual(thread.name, "Thread-5 (func)")
|
||||||
|
|
||||||
|
def test_args_argument(self):
|
||||||
|
# bpo-45735: Using list or tuple as *args* in constructor could
|
||||||
|
# achieve the same effect.
|
||||||
|
num_list = [1]
|
||||||
|
num_tuple = (1,)
|
||||||
|
|
||||||
|
str_list = ["str"]
|
||||||
|
str_tuple = ("str",)
|
||||||
|
|
||||||
|
list_in_tuple = ([1],)
|
||||||
|
tuple_in_list = [(1,)]
|
||||||
|
|
||||||
|
test_cases = (
|
||||||
|
(num_list, lambda arg: self.assertEqual(arg, 1)),
|
||||||
|
(num_tuple, lambda arg: self.assertEqual(arg, 1)),
|
||||||
|
(str_list, lambda arg: self.assertEqual(arg, "str")),
|
||||||
|
(str_tuple, lambda arg: self.assertEqual(arg, "str")),
|
||||||
|
(list_in_tuple, lambda arg: self.assertEqual(arg, [1])),
|
||||||
|
(tuple_in_list, lambda arg: self.assertEqual(arg, (1,)))
|
||||||
|
)
|
||||||
|
|
||||||
|
for args, target in test_cases:
|
||||||
|
with self.subTest(target=target, args=args):
|
||||||
|
t = threading.Thread(target=target, args=args)
|
||||||
|
t.start()
|
||||||
|
|
||||||
@cpython_only
|
@cpython_only
|
||||||
def test_disallow_instantiation(self):
|
def test_disallow_instantiation(self):
|
||||||
# Ensure that the type disallows instantiation (bpo-43916)
|
# Ensure that the type disallows instantiation (bpo-43916)
|
||||||
|
|
|
@ -852,7 +852,7 @@ class Thread:
|
||||||
*name* is the thread name. By default, a unique name is constructed of
|
*name* is the thread name. By default, a unique name is constructed of
|
||||||
the form "Thread-N" where N is a small decimal number.
|
the form "Thread-N" where N is a small decimal number.
|
||||||
|
|
||||||
*args* is the argument tuple for the target invocation. Defaults to ().
|
*args* is a list or tuple of arguments for the target invocation. Defaults to ().
|
||||||
|
|
||||||
*kwargs* is a dictionary of keyword arguments for the target
|
*kwargs* is a dictionary of keyword arguments for the target
|
||||||
invocation. Defaults to {}.
|
invocation. Defaults to {}.
|
||||||
|
|
|
@ -2004,6 +2004,7 @@ Yuxiao Zeng
|
||||||
Uwe Zessin
|
Uwe Zessin
|
||||||
Cheng Zhang
|
Cheng Zhang
|
||||||
George Zhang
|
George Zhang
|
||||||
|
Charlie Zhao
|
||||||
Kai Zhu
|
Kai Zhu
|
||||||
Tarek Ziadé
|
Tarek Ziadé
|
||||||
Jelle Zijlstra
|
Jelle Zijlstra
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue