mirror of https://github.com/python/cpython
Merged revisions 68915 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r68915 | jesse.noller | 2009-01-24 21:36:13 -0600 (Sat, 24 Jan 2009) | 1 line Properly document multiprocessing's logging support, resolve outstanding issues with the custom levels ........
This commit is contained in:
parent
5b19e62b88
commit
8b56d47d01
|
@ -1857,30 +1857,74 @@ handler type) for messages from different processes to get mixed up.
|
||||||
Returns the logger used by :mod:`multiprocessing`. If necessary, a new one
|
Returns the logger used by :mod:`multiprocessing`. If necessary, a new one
|
||||||
will be created.
|
will be created.
|
||||||
|
|
||||||
When first created the logger has level :data:`logging.NOTSET` and has a
|
When first created the logger has level :data:`logging.NOTSET` and no
|
||||||
handler which sends output to :data:`sys.stderr` using format
|
default handler. Messages sent to this logger will not by default propagate
|
||||||
``'[%(levelname)s/%(processName)s] %(message)s'``. (The logger allows use of
|
to the root logger.
|
||||||
the non-standard ``'%(processName)s'`` format.) Message sent to this logger
|
|
||||||
will not by default propagate to the root logger.
|
|
||||||
|
|
||||||
Note that on Windows child processes will only inherit the level of the
|
Note that on Windows child processes will only inherit the level of the
|
||||||
parent process's logger -- any other customization of the logger will not be
|
parent process's logger -- any other customization of the logger will not be
|
||||||
inherited.
|
inherited.
|
||||||
|
|
||||||
|
.. currentmodule:: multiprocessing
|
||||||
|
.. function:: log_to_stderr()
|
||||||
|
|
||||||
|
This function performs a call to :func:`get_logger` but in addition to
|
||||||
|
returning the logger created by get_logger, it adds a handler which sends
|
||||||
|
output to :data:`sys.stderr` using format
|
||||||
|
``'[%(levelname)s/%(processName)s] %(message)s'``.
|
||||||
|
|
||||||
Below is an example session with logging turned on::
|
Below is an example session with logging turned on::
|
||||||
|
|
||||||
>>> import multiprocessing, logging
|
>>> import multiprocessing, logging
|
||||||
>>> logger = multiprocessing.get_logger()
|
>>> logger = multiprocessing.log_to_stderr()
|
||||||
>>> logger.setLevel(logging.INFO)
|
>>> logger.setLevel(logging.INFO)
|
||||||
>>> logger.warning('doomed')
|
>>> logger.warning('doomed')
|
||||||
[WARNING/MainProcess] doomed
|
[WARNING/MainProcess] doomed
|
||||||
>>> m = multiprocessing.Manager()
|
>>> m = multiprocessing.Manager()
|
||||||
[INFO/SyncManager-1] child process calling self.run()
|
[INFO/SyncManager-1] child process calling self.run()
|
||||||
[INFO/SyncManager-1] manager bound to '\\\\.\\pipe\\pyc-2776-0-lj0tfa'
|
[INFO/SyncManager-1] created temp directory /.../pymp-Wh47O_
|
||||||
|
[INFO/SyncManager-1] manager serving at '/.../listener-lWsERs'
|
||||||
>>> del m
|
>>> del m
|
||||||
[INFO/MainProcess] sending shutdown message to manager
|
[INFO/MainProcess] sending shutdown message to manager
|
||||||
[INFO/SyncManager-1] manager exiting with exitcode 0
|
[INFO/SyncManager-1] manager exiting with exitcode 0
|
||||||
|
|
||||||
|
In addition to having these two logging functions, the multiprocessing also
|
||||||
|
exposes two additional logging level attributes. These are :const:`SUBWARNING`
|
||||||
|
and :const:`SUBDEBUG`. The table below illustrates where theses fit in the
|
||||||
|
normal level hierarchy.
|
||||||
|
|
||||||
|
+----------------+----------------+
|
||||||
|
| Level | Numeric value |
|
||||||
|
+================+================+
|
||||||
|
| ``SUBWARNING`` | 25 |
|
||||||
|
+----------------+----------------+
|
||||||
|
| ``SUBDEBUG`` | 5 |
|
||||||
|
+----------------+----------------+
|
||||||
|
|
||||||
|
For a full table of logging levels, see the :mod:`logging` module.
|
||||||
|
|
||||||
|
These additional logging levels are used primarily for certain debug messages
|
||||||
|
within the multiprocessing module. Below is the same example as above, except
|
||||||
|
with :const:`SUBDEBUG` enabled::
|
||||||
|
|
||||||
|
>>> import multiprocessing, logging
|
||||||
|
>>> logger = multiprocessing.log_to_stderr()
|
||||||
|
>>> logger.setLevel(multiprocessing.SUBDEBUG)
|
||||||
|
>>> logger.warning('doomed')
|
||||||
|
[WARNING/MainProcess] doomed
|
||||||
|
>>> m = multiprocessing.Manager()
|
||||||
|
[INFO/SyncManager-1] child process calling self.run()
|
||||||
|
[INFO/SyncManager-1] created temp directory /.../pymp-djGBXN
|
||||||
|
[INFO/SyncManager-1] manager serving at '/.../pymp-djGBXN/listener-knBYGe'
|
||||||
|
>>> del m
|
||||||
|
[SUBDEBUG/MainProcess] finalizer calling ...
|
||||||
|
[INFO/MainProcess] sending shutdown message to manager
|
||||||
|
[DEBUG/SyncManager-1] manager received shutdown message
|
||||||
|
[SUBDEBUG/SyncManager-1] calling <Finalize object, callback=unlink, ...
|
||||||
|
[SUBDEBUG/SyncManager-1] finalizer calling <built-in function unlink> ...
|
||||||
|
[SUBDEBUG/SyncManager-1] calling <Finalize object, dead>
|
||||||
|
[SUBDEBUG/SyncManager-1] finalizer calling <function rmtree at 0x5aa730> ...
|
||||||
|
[INFO/SyncManager-1] manager exiting with exitcode 0
|
||||||
|
|
||||||
The :mod:`multiprocessing.dummy` module
|
The :mod:`multiprocessing.dummy` module
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -48,7 +48,7 @@ __all__ = [
|
||||||
'allow_connection_pickling', 'BufferTooShort', 'TimeoutError',
|
'allow_connection_pickling', 'BufferTooShort', 'TimeoutError',
|
||||||
'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition',
|
'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition',
|
||||||
'Event', 'Queue', 'JoinableQueue', 'Pool', 'Value', 'Array',
|
'Event', 'Queue', 'JoinableQueue', 'Pool', 'Value', 'Array',
|
||||||
'RawValue', 'RawArray'
|
'RawValue', 'RawArray', 'SUBDEBUG', 'SUBWARNING',
|
||||||
]
|
]
|
||||||
|
|
||||||
__author__ = 'R. Oudkerk (r.m.oudkerk@gmail.com)'
|
__author__ = 'R. Oudkerk (r.m.oudkerk@gmail.com)'
|
||||||
|
@ -61,6 +61,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from multiprocessing.process import Process, current_process, active_children
|
from multiprocessing.process import Process, current_process, active_children
|
||||||
|
from multiprocessing.util import SUBDEBUG, SUBWARNING
|
||||||
|
|
||||||
#
|
#
|
||||||
# Exceptions
|
# Exceptions
|
||||||
|
|
|
@ -17,7 +17,8 @@ from multiprocessing.process import current_process, active_children
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'sub_debug', 'debug', 'info', 'sub_warning', 'get_logger',
|
'sub_debug', 'debug', 'info', 'sub_warning', 'get_logger',
|
||||||
'log_to_stderr', 'get_temp_dir', 'register_after_fork',
|
'log_to_stderr', 'get_temp_dir', 'register_after_fork',
|
||||||
'is_exiting', 'Finalize', 'ForkAwareThreadLock', 'ForkAwareLocal'
|
'is_exiting', 'Finalize', 'ForkAwareThreadLock', 'ForkAwareLocal',
|
||||||
|
'SUBDEBUG', 'SUBWARNING',
|
||||||
]
|
]
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -57,19 +58,27 @@ def get_logger():
|
||||||
Returns logger used by multiprocessing
|
Returns logger used by multiprocessing
|
||||||
'''
|
'''
|
||||||
global _logger
|
global _logger
|
||||||
|
import logging, atexit
|
||||||
|
|
||||||
if not _logger:
|
logging._acquireLock()
|
||||||
import logging, atexit
|
try:
|
||||||
|
if not _logger:
|
||||||
|
|
||||||
# XXX multiprocessing should cleanup before logging
|
_logger = logging.getLogger(LOGGER_NAME)
|
||||||
if hasattr(atexit, 'unregister'):
|
_logger.propagate = 0
|
||||||
atexit.unregister(_exit_function)
|
logging.addLevelName(SUBDEBUG, 'SUBDEBUG')
|
||||||
atexit.register(_exit_function)
|
logging.addLevelName(SUBWARNING, 'SUBWARNING')
|
||||||
else:
|
|
||||||
atexit._exithandlers.remove((_exit_function, (), {}))
|
|
||||||
atexit._exithandlers.append((_exit_function, (), {}))
|
|
||||||
|
|
||||||
_logger = logging.getLogger(LOGGER_NAME)
|
# XXX multiprocessing should cleanup before logging
|
||||||
|
if hasattr(atexit, 'unregister'):
|
||||||
|
atexit.unregister(_exit_function)
|
||||||
|
atexit.register(_exit_function)
|
||||||
|
else:
|
||||||
|
atexit._exithandlers.remove((_exit_function, (), {}))
|
||||||
|
atexit._exithandlers.append((_exit_function, (), {}))
|
||||||
|
|
||||||
|
finally:
|
||||||
|
logging._releaseLock()
|
||||||
|
|
||||||
return _logger
|
return _logger
|
||||||
|
|
||||||
|
@ -79,14 +88,17 @@ def log_to_stderr(level=None):
|
||||||
'''
|
'''
|
||||||
global _log_to_stderr
|
global _log_to_stderr
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
formatter = logging.Formatter(DEFAULT_LOGGING_FORMAT)
|
formatter = logging.Formatter(DEFAULT_LOGGING_FORMAT)
|
||||||
handler = logging.StreamHandler()
|
handler = logging.StreamHandler()
|
||||||
handler.setFormatter(formatter)
|
handler.setFormatter(formatter)
|
||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
if level is not None:
|
|
||||||
|
if level:
|
||||||
logger.setLevel(level)
|
logger.setLevel(level)
|
||||||
_log_to_stderr = True
|
_log_to_stderr = True
|
||||||
|
return _logger
|
||||||
|
|
||||||
#
|
#
|
||||||
# Function returning a temp directory which will be removed on exit
|
# Function returning a temp directory which will be removed on exit
|
||||||
|
|
|
@ -778,3 +778,4 @@ Siebren van der Zee
|
||||||
Uwe Zessin
|
Uwe Zessin
|
||||||
Tarek ZiadŽ
|
Tarek ZiadŽ
|
||||||
Peter Åstrand
|
Peter Åstrand
|
||||||
|
Jesse Noller
|
||||||
|
|
|
@ -92,6 +92,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Fix and properly document the multiprocessing module's logging
|
||||||
|
support, expose the internal levels and provide proper usage
|
||||||
|
examples.
|
||||||
|
|
||||||
- Issue #5387: Fixed mmap.move crash by integer overflow.
|
- Issue #5387: Fixed mmap.move crash by integer overflow.
|
||||||
|
|
||||||
- Issue #5261: Patch multiprocessing's semaphore.c to support context
|
- Issue #5261: Patch multiprocessing's semaphore.c to support context
|
||||||
|
|
Loading…
Reference in New Issue