Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 41faa54

Browse files
committed
merge r68915 to py3k
1 parent cddcf44 commit 41faa54

5 files changed

Lines changed: 82 additions & 20 deletions

File tree

Doc/library/multiprocessing.rst

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,30 +1857,74 @@ handler type) for messages from different processes to get mixed up.
18571857
Returns the logger used by :mod:`multiprocessing`. If necessary, a new one
18581858
will be created.
18591859

1860-
When first created the logger has level :data:`logging.NOTSET` and has a
1861-
handler which sends output to :data:`sys.stderr` using format
1862-
``'[%(levelname)s/%(processName)s] %(message)s'``. (The logger allows use of
1863-
the non-standard ``'%(processName)s'`` format.) Message sent to this logger
1864-
will not by default propagate to the root logger.
1860+
When first created the logger has level :data:`logging.NOTSET` and no
1861+
default handler. Messages sent to this logger will not by default propagate
1862+
to the root logger.
18651863

18661864
Note that on Windows child processes will only inherit the level of the
18671865
parent process's logger -- any other customization of the logger will not be
18681866
inherited.
18691867

1868+
.. currentmodule:: multiprocessing
1869+
.. function:: log_to_stderr()
1870+
1871+
This function performs a call to :func:`get_logger` but in addition to
1872+
returning the logger created by get_logger, it adds a handler which sends
1873+
output to :data:`sys.stderr` using format
1874+
``'[%(levelname)s/%(processName)s] %(message)s'``.
1875+
18701876
Below is an example session with logging turned on::
18711877

18721878
>>> import multiprocessing, logging
1873-
>>> logger = multiprocessing.get_logger()
1879+
>>> logger = multiprocessing.log_to_stderr()
18741880
>>> logger.setLevel(logging.INFO)
18751881
>>> logger.warning('doomed')
18761882
[WARNING/MainProcess] doomed
18771883
>>> m = multiprocessing.Manager()
18781884
[INFO/SyncManager-1] child process calling self.run()
1879-
[INFO/SyncManager-1] manager bound to '\\\\.\\pipe\\pyc-2776-0-lj0tfa'
1885+
[INFO/SyncManager-1] created temp directory /.../pymp-Wh47O_
1886+
[INFO/SyncManager-1] manager serving at '/.../listener-lWsERs'
18801887
>>> del m
18811888
[INFO/MainProcess] sending shutdown message to manager
18821889
[INFO/SyncManager-1] manager exiting with exitcode 0
18831890

1891+
In addition to having these two logging functions, the multiprocessing also
1892+
exposes two additional logging level attributes. These are :const:`SUBWARNING`
1893+
and :const:`SUBDEBUG`. The table below illustrates where theses fit in the
1894+
normal level hierarchy.
1895+
1896+
+----------------+----------------+
1897+
| Level | Numeric value |
1898+
+================+================+
1899+
| ``SUBWARNING`` | 25 |
1900+
+----------------+----------------+
1901+
| ``SUBDEBUG`` | 5 |
1902+
+----------------+----------------+
1903+
1904+
For a full table of logging levels, see the :mod:`logging` module.
1905+
1906+
These additional logging levels are used primarily for certain debug messages
1907+
within the multiprocessing module. Below is the same example as above, except
1908+
with :const:`SUBDEBUG` enabled::
1909+
1910+
>>> import multiprocessing, logging
1911+
>>> logger = multiprocessing.log_to_stderr()
1912+
>>> logger.setLevel(multiprocessing.SUBDEBUG)
1913+
>>> logger.warning('doomed')
1914+
[WARNING/MainProcess] doomed
1915+
>>> m = multiprocessing.Manager()
1916+
[INFO/SyncManager-1] child process calling self.run()
1917+
[INFO/SyncManager-1] created temp directory /.../pymp-djGBXN
1918+
[INFO/SyncManager-1] manager serving at '/.../pymp-djGBXN/listener-knBYGe'
1919+
>>> del m
1920+
[SUBDEBUG/MainProcess] finalizer calling ...
1921+
[INFO/MainProcess] sending shutdown message to manager
1922+
[DEBUG/SyncManager-1] manager received shutdown message
1923+
[SUBDEBUG/SyncManager-1] calling <Finalize object, callback=unlink, ...
1924+
[SUBDEBUG/SyncManager-1] finalizer calling <built-in function unlink> ...
1925+
[SUBDEBUG/SyncManager-1] calling <Finalize object, dead>
1926+
[SUBDEBUG/SyncManager-1] finalizer calling <function rmtree at 0x5aa730> ...
1927+
[INFO/SyncManager-1] manager exiting with exitcode 0
18841928

18851929
The :mod:`multiprocessing.dummy` module
18861930
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Lib/multiprocessing/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
'allow_connection_pickling', 'BufferTooShort', 'TimeoutError',
4949
'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition',
5050
'Event', 'Queue', 'JoinableQueue', 'Pool', 'Value', 'Array',
51-
'RawValue', 'RawArray'
51+
'RawValue', 'RawArray', 'SUBDEBUG', 'SUBWARNING',
5252
]
5353

5454
__author__ = 'R. Oudkerk ([email protected])'
@@ -61,6 +61,7 @@
6161
import sys
6262

6363
from multiprocessing.process import Process, current_process, active_children
64+
from multiprocessing.util import SUBDEBUG, SUBWARNING
6465

6566
#
6667
# Exceptions

Lib/multiprocessing/util.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
__all__ = [
1818
'sub_debug', 'debug', 'info', 'sub_warning', 'get_logger',
1919
'log_to_stderr', 'get_temp_dir', 'register_after_fork',
20-
'is_exiting', 'Finalize', 'ForkAwareThreadLock', 'ForkAwareLocal'
20+
'is_exiting', 'Finalize', 'ForkAwareThreadLock', 'ForkAwareLocal',
21+
'SUBDEBUG', 'SUBWARNING',
2122
]
2223

2324
#
@@ -57,19 +58,27 @@ def get_logger():
5758
Returns logger used by multiprocessing
5859
'''
5960
global _logger
61+
import logging, atexit
6062

61-
if not _logger:
62-
import logging, atexit
63+
logging._acquireLock()
64+
try:
65+
if not _logger:
6366

64-
# XXX multiprocessing should cleanup before logging
65-
if hasattr(atexit, 'unregister'):
66-
atexit.unregister(_exit_function)
67-
atexit.register(_exit_function)
68-
else:
69-
atexit._exithandlers.remove((_exit_function, (), {}))
70-
atexit._exithandlers.append((_exit_function, (), {}))
67+
_logger = logging.getLogger(LOGGER_NAME)
68+
_logger.propagate = 0
69+
logging.addLevelName(SUBDEBUG, 'SUBDEBUG')
70+
logging.addLevelName(SUBWARNING, 'SUBWARNING')
71+
72+
# XXX multiprocessing should cleanup before logging
73+
if hasattr(atexit, 'unregister'):
74+
atexit.unregister(_exit_function)
75+
atexit.register(_exit_function)
76+
else:
77+
atexit._exithandlers.remove((_exit_function, (), {}))
78+
atexit._exithandlers.append((_exit_function, (), {}))
7179

72-
_logger = logging.getLogger(LOGGER_NAME)
80+
finally:
81+
logging._releaseLock()
7382

7483
return _logger
7584

@@ -79,14 +88,17 @@ def log_to_stderr(level=None):
7988
'''
8089
global _log_to_stderr
8190
import logging
91+
8292
logger = get_logger()
8393
formatter = logging.Formatter(DEFAULT_LOGGING_FORMAT)
8494
handler = logging.StreamHandler()
8595
handler.setFormatter(formatter)
8696
logger.addHandler(handler)
87-
if level is not None:
97+
98+
if level:
8899
logger.setLevel(level)
89100
_log_to_stderr = True
101+
return _logger
90102

91103
#
92104
# Function returning a temp directory which will be removed on exit

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,3 +785,4 @@ Siebren van der Zee
785785
Uwe Zessin
786786
Tarek Ziad�
787787
Peter �strand
788+
Jesse Noller

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ Core and Builtins
139139
Library
140140
-------
141141

142+
- Fix and properly document the multiprocessing module's logging
143+
support, expose the internal levels and provide proper usage
144+
examples.
145+
142146
- Issue #1672332: fix unpickling of subnormal floats, which was
143147
producing a ValueError on some platforms.
144148

0 commit comments

Comments
 (0)