|
Description:
Have you ever tried to log an exception of unknown type ? What's in it ? How to fetch stack trace ? Will str(e) return plain ascii or international chars ? Is logger ready for it ? This recipe provides a formatting function.
Source: Text Source
__all__ = [ "exc_string", "trace_string", "force_string",
"get_exc_string_encoding", "set_exc_string_encoding" ]
from sys import exc_info
from traceback import extract_stack, extract_tb
from os import path
exc_string_encoding = "windows-1251"
def get_exc_string_encoding():
return exc_string_encoding
def set_exc_string_encoding(encoding):
global exc_string_encoding
exc_string_encoding = encoding
force_string_translate_map = " ????????\t ?? ??????????????????" + "".join([ chr(i) for i in range(32, 256) ])
def force_string(v):
if isinstance(v, str):
v = v.decode(exc_string_encoding, "replace").encode(exc_string_encoding, "replace")
return v.translate(force_string_translate_map)
elif isinstance(v, unicode):
v = v.encode(exc_string_encoding, "replace")
return v.translate(force_string_translate_map)
else:
try:
v = str(v)
except:
return "unable to convert %s to string, str() failed" % v.__class__.__name__
else:
return force_string(v)
def _reversed(r):
result = list(r)
result.reverse()
return result
def trace_string(tb = None):
return " <- ".join([ force_string("%s() (%s:%s)" % (m, path.split(f)[1], n))
for f, n, m, u in _reversed(tb or extract_stack()[:-1]) ])
def exc_string():
try:
t, v, tb = exc_info()
if t is None:
return "no exception"
if v is not None:
v = force_string(v)
else:
v = force_string(t)
if hasattr(t, "__name__"):
t = t.__name__
else:
t = type(t).__name__
return "%s(\"%s\") in %s" % (t, v, trace_string(extract_tb(tb)))
except:
return "exc_string() failed to extract exception string"
Discussion:
It's always painful to try to log an exception. You have no idea what's in it and str() won't help, because (1) str() returns a string in unknown encoding likely unsuitable for your logger-of-the-week or worse (2) str() fails itself. Besides, you need to fetch stack trace from somewhere else and it's huge and ugly.
This recipe provides an exc_string() function which hides all this and returns a pretty single line with exception text and stack trace all in specified encoding.
|