mirror of
https://github.com/python/cpython.git
synced 2024-11-23 18:04:37 +08:00
Closes #20537: logging methods now accept an exception instance as well as a Boolean value or exception tuple. Thanks to Yury Selivanov for the patch.
This commit is contained in:
parent
4ff91eb5e3
commit
02a8f9e9ac
@ -155,11 +155,13 @@ is the module's name in the Python package namespace.
|
||||
*msg* using the string formatting operator. (Note that this means that you can
|
||||
use keywords in the format string, together with a single dictionary argument.)
|
||||
|
||||
There are three keyword arguments in *kwargs* which are inspected: *exc_info*
|
||||
which, if it does not evaluate as false, causes exception information to be
|
||||
There are three keyword arguments in *kwargs* which are inspected:
|
||||
*exc_info*, *stack_info*, and *extra*.
|
||||
|
||||
If *exc_info* does not evaluate as false, it causes exception information to be
|
||||
added to the logging message. If an exception tuple (in the format returned by
|
||||
:func:`sys.exc_info`) is provided, it is used; otherwise, :func:`sys.exc_info`
|
||||
is called to get the exception information.
|
||||
:func:`sys.exc_info`) or an exception instance is provided, it is used;
|
||||
otherwise, :func:`sys.exc_info` is called to get the exception information.
|
||||
|
||||
The second optional keyword argument is *stack_info*, which defaults to
|
||||
``False``. If true, stack information is added to the logging
|
||||
@ -216,6 +218,9 @@ is the module's name in the Python package namespace.
|
||||
.. versionadded:: 3.2
|
||||
The *stack_info* parameter was added.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
The *exc_info* parameter can now accept exception instances.
|
||||
|
||||
|
||||
.. method:: Logger.info(msg, *args, **kwargs)
|
||||
|
||||
|
@ -1302,12 +1302,11 @@ class Logger(Filterer):
|
||||
if self.isEnabledFor(ERROR):
|
||||
self._log(ERROR, msg, args, **kwargs)
|
||||
|
||||
def exception(self, msg, *args, **kwargs):
|
||||
def exception(self, msg, *args, exc_info=True, **kwargs):
|
||||
"""
|
||||
Convenience method for logging an ERROR with exception information.
|
||||
"""
|
||||
kwargs['exc_info'] = True
|
||||
self.error(msg, *args, **kwargs)
|
||||
self.error(msg, *args, exc_info=exc_info, **kwargs)
|
||||
|
||||
def critical(self, msg, *args, **kwargs):
|
||||
"""
|
||||
@ -1402,7 +1401,9 @@ class Logger(Filterer):
|
||||
else: # pragma: no cover
|
||||
fn, lno, func = "(unknown file)", 0, "(unknown function)"
|
||||
if exc_info:
|
||||
if not isinstance(exc_info, tuple):
|
||||
if isinstance(exc_info, BaseException):
|
||||
exc_info = (type(exc_info), exc_info, exc_info.__traceback__)
|
||||
elif not isinstance(exc_info, tuple):
|
||||
exc_info = sys.exc_info()
|
||||
record = self.makeRecord(self.name, level, fn, lno, msg, args,
|
||||
exc_info, func, extra, sinfo)
|
||||
@ -1612,12 +1613,11 @@ class LoggerAdapter(object):
|
||||
"""
|
||||
self.log(ERROR, msg, *args, **kwargs)
|
||||
|
||||
def exception(self, msg, *args, **kwargs):
|
||||
def exception(self, msg, *args, exc_info=True, **kwargs):
|
||||
"""
|
||||
Delegate an exception call to the underlying logger.
|
||||
"""
|
||||
kwargs["exc_info"] = True
|
||||
self.log(ERROR, msg, *args, **kwargs)
|
||||
self.log(ERROR, msg, *args, exc_info=exc_info, **kwargs)
|
||||
|
||||
def critical(self, msg, *args, **kwargs):
|
||||
"""
|
||||
@ -1796,14 +1796,13 @@ def error(msg, *args, **kwargs):
|
||||
basicConfig()
|
||||
root.error(msg, *args, **kwargs)
|
||||
|
||||
def exception(msg, *args, **kwargs):
|
||||
def exception(msg, *args, exc_info=True, **kwargs):
|
||||
"""
|
||||
Log a message with severity 'ERROR' on the root logger, with exception
|
||||
information. If the logger has no handlers, basicConfig() is called to add
|
||||
a console handler with a pre-defined format.
|
||||
"""
|
||||
kwargs['exc_info'] = True
|
||||
error(msg, *args, **kwargs)
|
||||
error(msg, *args, exc_info=exc_info, **kwargs)
|
||||
|
||||
def warning(msg, *args, **kwargs):
|
||||
"""
|
||||
|
@ -3712,6 +3712,19 @@ class LoggerAdapterTest(unittest.TestCase):
|
||||
self.assertEqual(record.exc_info,
|
||||
(exc.__class__, exc, exc.__traceback__))
|
||||
|
||||
def test_exception_excinfo(self):
|
||||
try:
|
||||
1 / 0
|
||||
except ZeroDivisionError as e:
|
||||
exc = e
|
||||
|
||||
self.adapter.exception('exc_info test', exc_info=exc)
|
||||
|
||||
self.assertEqual(len(self.recording.records), 1)
|
||||
record = self.recording.records[0]
|
||||
self.assertEqual(record.exc_info,
|
||||
(exc.__class__, exc, exc.__traceback__))
|
||||
|
||||
def test_critical(self):
|
||||
msg = 'critical test! %r'
|
||||
self.adapter.critical(msg, self.recording)
|
||||
|
@ -132,6 +132,9 @@ Core and Builtins
|
||||
Library
|
||||
-------
|
||||
|
||||
- Issue #20537: logging methods now accept an exception instance as well as a
|
||||
Boolean value or exception tuple. Thanks to Yury Selivanov for the patch.
|
||||
|
||||
- Issue #22384: An exception in Tkinter callback no longer crashes the program
|
||||
when it is run with pythonw.exe.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user