[Python-checkins] r88618 - in python/branches/py3k: Doc/library/multiprocessing.rst Doc/library/threading.rst Lib/multiprocessing/process.py Lib/test/test_multiprocessing.py Lib/test/test_threading.py Lib/threading.py Misc/NEWS

antoine.pitrou python-checkins at python.org
Fri Feb 25 23:07:43 CET 2011


Author: antoine.pitrou
Date: Fri Feb 25 23:07:43 2011
New Revision: 88618

Log:
Issue #6064: Add a `daemon` keyword argument to the threading.Thread
and multiprocessing.Process constructors in order to override the
default behaviour of inheriting the daemonic property from the current
thread/process.




Modified:
   python/branches/py3k/Doc/library/multiprocessing.rst
   python/branches/py3k/Doc/library/threading.rst
   python/branches/py3k/Lib/multiprocessing/process.py
   python/branches/py3k/Lib/test/test_multiprocessing.py
   python/branches/py3k/Lib/test/test_threading.py
   python/branches/py3k/Lib/threading.py
   python/branches/py3k/Misc/NEWS

Modified: python/branches/py3k/Doc/library/multiprocessing.rst
==============================================================================
--- python/branches/py3k/Doc/library/multiprocessing.rst	(original)
+++ python/branches/py3k/Doc/library/multiprocessing.rst	Fri Feb 25 23:07:43 2011
@@ -297,7 +297,7 @@
 :class:`Process` and exceptions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. class:: Process([group[, target[, name[, args[, kwargs]]]]])
+.. class:: Process([group[, target[, name[, args[, kwargs]]]]], *, daemon=None)
 
    Process objects represent activity that is run in a separate process. The
    :class:`Process` class has equivalents of all the methods of
@@ -312,13 +312,19 @@
    :sub:`1`,N\ :sub:`2`,...,N\ :sub:`k` is a sequence of integers whose length
    is determined by the *generation* of the process.  *args* is the argument
    tuple for the target invocation.  *kwargs* is a dictionary of keyword
-   arguments for the target invocation.  By default, no arguments are passed to
-   *target*.
+   arguments for the target invocation.  If provided, the keyword-only *daemon* argument
+   sets the process :attr:`daemon` flag to ``True`` or ``False``.  If ``None``
+   (the default), this flag will be inherited from the creating process.
+
+   By default, no arguments are passed to *target*.
 
    If a subclass overrides the constructor, it must make sure it invokes the
    base class constructor (:meth:`Process.__init__`) before doing anything else
    to the process.
 
+   .. versionchanged:: 3.3
+      Added the *daemon* argument.
+
    .. method:: run()
 
       Method representing the process's activity.

Modified: python/branches/py3k/Doc/library/threading.rst
==============================================================================
--- python/branches/py3k/Doc/library/threading.rst	(original)
+++ python/branches/py3k/Doc/library/threading.rst	Fri Feb 25 23:07:43 2011
@@ -241,7 +241,7 @@
 A thread can be flagged as a "daemon thread".  The significance of this flag is
 that the entire Python program exits when only daemon threads are left.  The
 initial value is inherited from the creating thread.  The flag can be set
-through the :attr:`daemon` property.
+through the :attr:`daemon` property or the *daemon* constructor argument.
 
 There is a "main thread" object; this corresponds to the initial thread of
 control in the Python program.  It is not a daemon thread.
@@ -254,7 +254,8 @@
 impossible to detect the termination of alien threads.
 
 
-.. class:: Thread(group=None, target=None, name=None, args=(), kwargs={})
+.. class:: Thread(group=None, target=None, name=None, args=(), kwargs={},
+                  verbose=None, *, daemon=None)
 
    This constructor should always be called with keyword arguments.  Arguments
    are:
@@ -273,10 +274,19 @@
    *kwargs* is a dictionary of keyword arguments for the target invocation.
    Defaults to ``{}``.
 
+   *verbose* is a flag used for debugging messages.
+
+   If not ``None``, *daemon* explicitly sets whether the thread is daemonic.
+   If ``None`` (the default), the daemonic property is inherited from the
+   current thread.
+
    If the subclass overrides the constructor, it must make sure to invoke the
    base class constructor (``Thread.__init__()``) before doing anything else to
    the thread.
 
+   .. versionchanged:: 3.3
+      Added the *daemon* argument.
+
    .. method:: start()
 
       Start the thread's activity.

Modified: python/branches/py3k/Lib/multiprocessing/process.py
==============================================================================
--- python/branches/py3k/Lib/multiprocessing/process.py	(original)
+++ python/branches/py3k/Lib/multiprocessing/process.py	Fri Feb 25 23:07:43 2011
@@ -91,12 +91,16 @@
     '''
     _Popen = None
 
-    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
+    def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
+                 *, daemon=None):
         assert group is None, 'group argument must be None for now'
         count = next(_current_process._counter)
         self._identity = _current_process._identity + (count,)
         self._authkey = _current_process._authkey
-        self._daemonic = _current_process._daemonic
+        if daemon is not None:
+            self._daemonic = daemon
+        else:
+            self._daemonic = _current_process._daemonic
         self._tempdir = _current_process._tempdir
         self._parent_pid = os.getpid()
         self._popen = None

Modified: python/branches/py3k/Lib/test/test_multiprocessing.py
==============================================================================
--- python/branches/py3k/Lib/test/test_multiprocessing.py	(original)
+++ python/branches/py3k/Lib/test/test_multiprocessing.py	Fri Feb 25 23:07:43 2011
@@ -163,6 +163,18 @@
         self.assertEqual(current.ident, os.getpid())
         self.assertEqual(current.exitcode, None)
 
+    def test_daemon_argument(self):
+        if self.TYPE == "threads":
+            return
+
+        # By default uses the current process's daemon flag.
+        proc0 = self.Process(target=self._test)
+        self.assertEquals(proc0.daemon, self.current_process().daemon)
+        proc1 = self.Process(target=self._test, daemon=True)
+        self.assertTrue(proc1.daemon)
+        proc2 = self.Process(target=self._test, daemon=False)
+        self.assertFalse(proc2.daemon)
+
     @classmethod
     def _test(cls, q, *args, **kwds):
         current = cls.current_process()

Modified: python/branches/py3k/Lib/test/test_threading.py
==============================================================================
--- python/branches/py3k/Lib/test/test_threading.py	(original)
+++ python/branches/py3k/Lib/test/test_threading.py	Fri Feb 25 23:07:43 2011
@@ -427,6 +427,14 @@
         t.daemon = True
         self.assertTrue('daemon' in repr(t))
 
+    def test_deamon_param(self):
+        t = threading.Thread()
+        self.assertFalse(t.daemon)
+        t = threading.Thread(daemon=False)
+        self.assertFalse(t.daemon)
+        t = threading.Thread(daemon=True)
+        self.assertTrue(t.daemon)
+
 
 class ThreadJoinOnShutdown(BaseTestCase):
 

Modified: python/branches/py3k/Lib/threading.py
==============================================================================
--- python/branches/py3k/Lib/threading.py	(original)
+++ python/branches/py3k/Lib/threading.py	Fri Feb 25 23:07:43 2011
@@ -622,7 +622,7 @@
     #XXX __exc_clear = _sys.exc_clear
 
     def __init__(self, group=None, target=None, name=None,
-                 args=(), kwargs=None, verbose=None):
+                 args=(), kwargs=None, verbose=None, *, daemon=None):
         assert group is None, "group argument must be None for now"
         _Verbose.__init__(self, verbose)
         if kwargs is None:
@@ -631,7 +631,10 @@
         self._name = str(name or _newname())
         self._args = args
         self._kwargs = kwargs
-        self._daemonic = self._set_daemon()
+        if daemon is not None:
+            self._daemonic = daemon
+        else:
+            self._daemonic = current_thread().daemon
         self._ident = None
         self._started = Event()
         self._stopped = False
@@ -648,10 +651,6 @@
             self._block.__init__()
         self._started._reset_internal_locks()
 
-    def _set_daemon(self):
-        # Overridden in _MainThread and _DummyThread
-        return current_thread().daemon
-
     def __repr__(self):
         assert self._initialized, "Thread.__init__() was not called"
         status = "initial"
@@ -948,15 +947,12 @@
 class _MainThread(Thread):
 
     def __init__(self):
-        Thread.__init__(self, name="MainThread")
+        Thread.__init__(self, name="MainThread", daemon=False)
         self._started.set()
         self._set_ident()
         with _active_limbo_lock:
             _active[self._ident] = self
 
-    def _set_daemon(self):
-        return False
-
     def _exitfunc(self):
         self._stop()
         t = _pickSomeNonDaemonThread()
@@ -988,7 +984,7 @@
 class _DummyThread(Thread):
 
     def __init__(self):
-        Thread.__init__(self, name=_newname("Dummy-%d"))
+        Thread.__init__(self, name=_newname("Dummy-%d"), daemon=True)
 
         # Thread._block consumes an OS-level locking primitive, which
         # can never be used by a _DummyThread.  Since a _DummyThread
@@ -1000,9 +996,6 @@
         with _active_limbo_lock:
             _active[self._ident] = self
 
-    def _set_daemon(self):
-        return True
-
     def join(self, timeout=None):
         assert False, "cannot join a dummy thread"
 

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Fri Feb 25 23:07:43 2011
@@ -35,6 +35,11 @@
 Library
 -------
 
+- Issue #6064: Add a ``daemon`` keyword argument to the threading.Thread
+  and multiprocessing.Process constructors in order to override the
+  default behaviour of inheriting the daemonic property from the current
+  thread/process.
+
 - Issue #10956: Buffered I/O classes retry reading or writing after a signal
   has arrived and the handler returned successfully.
 


More information about the Python-checkins mailing list