Skip to content

Commit 708e026

Browse files
CharlieZhao95tim-one
authored andcommitted
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 <[email protected]>
1 parent 9288420 commit 708e026

File tree

6 files changed

+82
-3
lines changed

6 files changed

+82
-3
lines changed

Doc/library/multiprocessing.rst

+16-1
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,9 @@ The :mod:`multiprocessing` package mostly replicates the API of the
485485
to ``True`` or ``False``. If ``None`` (the default), this flag will be
486486
inherited from the creating process.
487487

488-
By default, no arguments are passed to *target*.
488+
By default, no arguments are passed to *target*. The *args* argument,
489+
which defaults to ``()``, can be used to specify a list or tuple of the arguments
490+
to pass to *target*.
489491

490492
If a subclass overrides the constructor, it must make sure it invokes the
491493
base class constructor (:meth:`Process.__init__`) before doing anything else
@@ -503,6 +505,19 @@ The :mod:`multiprocessing` package mostly replicates the API of the
503505
the target argument, if any, with sequential and keyword arguments taken
504506
from the *args* and *kwargs* arguments, respectively.
505507

508+
Using a list or tuple as the *args* argument passed to :class:`Process`
509+
achieves the same effect.
510+
511+
Example::
512+
513+
>>> from multiprocessing import Process
514+
>>> p = Process(target=print, args=[1])
515+
>>> p.run()
516+
1
517+
>>> p = Process(target=print, args=(1,))
518+
>>> p.run()
519+
1
520+
506521
.. method:: start()
507522

508523
Start the process's activity.

Doc/library/threading.rst

+14-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ since it is impossible to detect the termination of alien threads.
314314
or "Thread-*N* (target)" where "target" is ``target.__name__`` if the
315315
*target* argument is specified.
316316

317-
*args* is the argument tuple for the target invocation. Defaults to ``()``.
317+
*args* is a list or tuple of arguments for the target invocation. Defaults to ``()``.
318318

319319
*kwargs* is a dictionary of keyword arguments for the target invocation.
320320
Defaults to ``{}``.
@@ -353,6 +353,19 @@ since it is impossible to detect the termination of alien threads.
353353
the *target* argument, if any, with positional and keyword arguments taken
354354
from the *args* and *kwargs* arguments, respectively.
355355

356+
Using list or tuple as the *args* argument which passed to the :class:`Thread`
357+
could achieve the same effect.
358+
359+
Example::
360+
361+
>>> from threading import Thread
362+
>>> t = Thread(target=print, args=[1])
363+
>>> t.run()
364+
1
365+
>>> t = Thread(target=print, args=(1,))
366+
>>> t.run()
367+
1
368+
356369
.. method:: join(timeout=None)
357370

358371
Wait until the thread terminates. This blocks the calling thread until

Lib/test/_test_multiprocessing.py

+24
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,30 @@ def test_current(self):
247247
self.assertEqual(current.ident, os.getpid())
248248
self.assertEqual(current.exitcode, None)
249249

250+
def test_args_argument(self):
251+
# bpo-45735: Using list or tuple as *args* in constructor could
252+
# achieve the same effect.
253+
args_cases = (1, "str", [1], (1,))
254+
args_types = (list, tuple)
255+
256+
test_cases = itertools.product(args_cases, args_types)
257+
258+
for args, args_type in test_cases:
259+
with self.subTest(args=args, args_type=args_type):
260+
q = self.Queue(1)
261+
# pass a tuple or list as args
262+
p = self.Process(target=self._test_args, args=args_type((q, args)))
263+
p.daemon = True
264+
p.start()
265+
child_args = q.get()
266+
self.assertEqual(child_args, args)
267+
p.join()
268+
close_queue(q)
269+
270+
@classmethod
271+
def _test_args(cls, q, arg):
272+
q.put(arg)
273+
250274
def test_daemon_argument(self):
251275
if self.TYPE == "threads":
252276
self.skipTest('test not appropriate for {}'.format(self.TYPE))

Lib/test/test_threading.py

+26
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,32 @@ def func(): pass
123123
thread = threading.Thread(target=func)
124124
self.assertEqual(thread.name, "Thread-5 (func)")
125125

126+
def test_args_argument(self):
127+
# bpo-45735: Using list or tuple as *args* in constructor could
128+
# achieve the same effect.
129+
num_list = [1]
130+
num_tuple = (1,)
131+
132+
str_list = ["str"]
133+
str_tuple = ("str",)
134+
135+
list_in_tuple = ([1],)
136+
tuple_in_list = [(1,)]
137+
138+
test_cases = (
139+
(num_list, lambda arg: self.assertEqual(arg, 1)),
140+
(num_tuple, lambda arg: self.assertEqual(arg, 1)),
141+
(str_list, lambda arg: self.assertEqual(arg, "str")),
142+
(str_tuple, lambda arg: self.assertEqual(arg, "str")),
143+
(list_in_tuple, lambda arg: self.assertEqual(arg, [1])),
144+
(tuple_in_list, lambda arg: self.assertEqual(arg, (1,)))
145+
)
146+
147+
for args, target in test_cases:
148+
with self.subTest(target=target, args=args):
149+
t = threading.Thread(target=target, args=args)
150+
t.start()
151+
126152
@cpython_only
127153
def test_disallow_instantiation(self):
128154
# Ensure that the type disallows instantiation (bpo-43916)

Lib/threading.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ class is implemented.
852852
*name* is the thread name. By default, a unique name is constructed of
853853
the form "Thread-N" where N is a small decimal number.
854854
855-
*args* is the argument tuple for the target invocation. Defaults to ().
855+
*args* is a list or tuple of arguments for the target invocation. Defaults to ().
856856
857857
*kwargs* is a dictionary of keyword arguments for the target
858858
invocation. Defaults to {}.

Misc/ACKS

+1
Original file line numberDiff line numberDiff line change
@@ -2004,6 +2004,7 @@ Yuxiao Zeng
20042004
Uwe Zessin
20052005
Cheng Zhang
20062006
George Zhang
2007+
Charlie Zhao
20072008
Kai Zhu
20082009
Tarek Ziadé
20092010
Jelle Zijlstra

0 commit comments

Comments
 (0)