This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: logging.Formatter.format() assumes exception to support str() method which is not true for many libraries.
Type: enhancement Stage:
Components: Library (Lib) Versions: Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Piotr.Czachur, eric.araujo, vinay.sajip
Priority: normal Keywords:

Created on 2011-06-15 13:42 by Piotr.Czachur, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (2)
msg138369 - (view) Author: Piotr Czachur (Piotr.Czachur) Date: 2011-06-15 13:41
If I want my application to be bullet-proof against external libraries that can (and often do) raise Exception(u'nonascii'), I cannot use python's logger.exception() directly, as it will end up with UnicodeDecodeError. 

The reason is hidden in Formatter.format() which does:
    s = self._fmt % record.__dict__

One can use his own formatter that can handle UnicodeDecodeError, but many users are quite unaware of such issue and it would be great if Python can handle it by itself.


Here is a simple case.

>>> e = Exception(u'ą')
>>> logging.basicConfig()
>>> logging.getLogger('general').exception(u'ą')
ą
None
>>> logging.getLogger('general').exception(e)
Traceback (most recent call last):
  File "/usr/lib/python2.7/logging/__init__.py", line 842, in emit
    msg = self.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 719, in format
    return fmt.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 467, in format
    s = self._fmt % record.__dict__
UnicodeEncodeError: 'ascii' codec can't encode character u'\u0105' in position 0: ordinal not in range(128)
Logged from file <stdin>, line 1
>>> unicode(e)
u'\u0105'
>>> str(e)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u0105' in position 0: ordinal not in range(128)
>>>
msg138371 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2011-06-15 13:59
This is happening because if you pass an object instead of a string as the first argument in a logging call, it's treated as a message object whose __str__() will be called to get the actual message when it's needed, as documented here:

http://docs.python.org/howto/logging.html#arbitrary-object-messages

If, instead, you do it like this:

# coding: utf-8
import logging

logging.basicConfig()
try:
    raise Exception(u'ą')
except Exception:
    logging.getLogger('general').exception(u'An error occurred')

you get

ERROR:general:An error occurred
Traceback (most recent call last):
  File "bug_12339.py", line 6, in <module>
    raise Exception(u'ą')
Exception: \u0105
History
Date User Action Args
2022-04-11 14:57:18adminsetgithub: 56548
2011-06-15 13:59:44vinay.sajipsetstatus: open -> closed
resolution: not a bug
messages: + msg138371
2011-06-15 13:43:20eric.araujosetnosy: + vinay.sajip, eric.araujo
2011-06-15 13:42:00Piotr.Czachurcreate