Should logger.exception only be called inside an except block? Why?
Question: The docs for
[`logger.exception`](https://docs.python.org/2/library/logging.html#logging.Logger.exception)
mention:

> This method should only be called from an exception handler.

So usage should be somethnig like this:

    
    
    import logging, sys
    
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    handler = logging.StreamHandler(sys.stdout)
    handler.setLevel(logging.DEBUG)
    logger.addHandler(handler)
    
    try:
        errorerrorerror
    except NameError as e:
        logger.exception('debug message 1 {}'.format(e))
    

But when I tried doing it the "wrong" way, behaviour seemed to be just the
same:

    
    
    try:
        errorerrorerror
    except NameError as e:
        pass
    
    logger.exception('debug message 2 {}'.format(e))
    

What is the reason for that caveat mentioned in the docs? Is it _actually_
true that we can only use it in an except block, for some subtle reason not
evident here?

I am aware that in python 3 this has changed, but python documentation is
usually very consistent in mentioning these differences..


Answer: The method is _designed_ for use in an exception handler. As such the
documentation tells you this, by using the word _should_ , not _must_.

In the text of standards, _should_ and _must_ are rigidly defined; one means
_we advice you to do it this way, it'd be much better if you did_ , the other
means _it's an outright error if you don't do this_. See [RFC
2119](http://www.ietf.org/rfc/rfc2119.txt) for the IETF taskforce wording.

All `logging.exception()` does is set the `exc_info` keyword argument before
calling `logging.error()`. The `exc_info` argument is then later fleshed out
to include the _most recently handled exception_ , taken from
[`sys.exc_info()`](https://docs.python.org/2/library/sys.html#sys.exc_info).
It is then up to the formatter to include the exception message (via the
[`Formatter.format_exception()`
method](https://docs.python.org/2/library/logging.html#logging.Formatter.formatException)
to format the exception.

Because `sys.exc_info()` works both in the `except` suite and out, both
variants work. From a _code documentation point of view_ , it is just clearer
if you use it in the `except` handler.

You don't need to include the error message, really, because your log
formatter should already do that for you:

    
    
    logger.exception('debug message 2')  # exception should be included automatically
    

You can explicitly attach an exception to any log message with:

    
    
    logger.error('debug message 2', exc_info=sys.exc_info())
    

or any other 3-tuple value with the exception type, the exception value and a
traceback. Alternatively, set `exc_info=1` to have the logger retrieve the
information from `sys.exc_info()` itself.

See the documentation for
[`Logger.debug()`](https://docs.python.org/2/library/logging.html#logging.Logger.debug):

> _exc_info_ which, if it does not evaluate as false, causes exception
> information to be added to the logging message. If an exception tuple (in
> the format returned by `sys.exc_info()`) is provided, it is used; otherwise,
> `sys.exc_info()` is called to get the exception information.

