Log exception so traceback contains timestamp and level?

Peter Otten __peter__ at web.de
Mon Feb 8 05:06:01 EST 2021


On 07/02/2021 16:12, Peter J. Holzer wrote:
> On 2021-02-06 21:01:37 -0600, Skip Montanaro wrote:
>> The logging package can log exceptions and call stacks, but it does
>> (in my opinion) a suboptimal job of it. Consider this simple example:
>>>>> import logging
>>>>> FORMAT = '%(asctime)-15s %(levelname)s %(message)s'
>>>>> logging.basicConfig(format=FORMAT, force=True)
>>>>> log.warning("msg", stack_info=True)
>> 2021-02-06 20:46:52,399 WARNING msg
>> Stack (most recent call last):
>>    File "<stdin>", line 1, in <module>
>>
>> It formats the warning message just fine, but simply dumps the
>> traceback onto the stream with no timestamp or level. For my purposes,
>> this is more important for exceptions. (I'm just using the stack trace
>> feature as it's easier in a small example.) I would like to call
>> something like
> 
> I suspect that it just adds the stack trace to the message, so that you
> are left with a multi-line message.

If you are willing to process all multiline messages in the same way 
that simplifies your custom Formatter:

def make_formatter_class(prefix, style):

     class PrefixFormatter(logging.Formatter):
         prefix_template = logging._STYLES[style][0](prefix)
         prefix_uses_time = prefix_template.usesTime()

         def usesTime(self):
             return self.prefix_uses_time or super().usesTime()

         def format(self, record):
             # this is supposed to set asctime attribute implicitly:
             text = super().format(record)

             lines = text.splitlines(True)
             if len(lines) > 1:
                 prefix = self.prefix_template.format(record)
                 return "".join(
                     lines[:1] + [prefix + line for line in lines[1:]]
                 )
             return text

     return PrefixFormatter


# optional: monkey-patch to affect basicConfig()
logging.Formatter = make_formatter_class(
     prefix="X... %(asctime)s %(levelname)s ", style="%"
)



More information about the Python-list mailing list