Showing the right funcName when wrapping logger functionality in a custom class

前端 未结 8 1690
你的背包
你的背包 2021-02-01 16:31

This is the formatting string that I am using for logging:

\'%(asctime)s - %(levelname)-10s - %(funcName)s - %(message)s\'

But to show the logg

8条回答
  •  心在旅途
    2021-02-01 16:51

    This is fixed in Python 3.8 with addition of the stacklevel param. However, I took the current implementation of findCaller from cpython to make a Python 3.7 compatible version.

    Taken from a combination of the answers above:

    import sys,os
    
    #Get both logger's and this file's path so the wrapped logger can tell when its looking at the code stack outside of this file.
    _loggingfile = os.path.normcase(logging.__file__)
    if hasattr(sys, 'frozen'): #support for py2exe
        _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:])
    elif __file__[-4:].lower() in ['.pyc', '.pyo']:
        _srcfile = __file__[:-4] + '.py'
    else:
        _srcfile = __file__
    _srcfile = os.path.normcase(_srcfile)
    _wrongCallerFiles = set([_loggingfile, _srcfile])
    
    #Subclass the original logger and overwrite findCaller
    class WrappedLogger(logging.Logger):
        def __init__(self, name):
            logging.Logger.__init__(self, name)
    
        #Modified slightly from cpython's implementation https://github.com/python/cpython/blob/master/Lib/logging/__init__.py#L1374
        def findCaller(self, stack_info=False, stacklevel=1):
            """
            Find the stack frame of the caller so that we can note the source
            file name, line number and function name.
            """
            f = currentframe()
            #On some versions of IronPython, currentframe() returns None if
            #IronPython isn't run with -X:Frames.
            if f is not None:
                f = f.f_back
            orig_f = f
            while f and stacklevel > 1:
                f = f.f_back
                stacklevel -= 1
            if not f:
                f = orig_f
            rv = "(unknown file)", 0, "(unknown function)", None
            while hasattr(f, "f_code"):
                co = f.f_code
                filename = os.path.normcase(co.co_filename)
                if filename in _wrongCallerFiles:
                    f = f.f_back
                    continue
                sinfo = None
                if stack_info:
                    sio = io.StringIO()
                    sio.write('Stack (most recent call last):\n')
                    traceback.print_stack(f, file=sio)
                    sinfo = sio.getvalue()
                    if sinfo[-1] == '\n':
                    sinfo = sinfo[:-1]
                sio.close()
            rv = (co.co_filename, f.f_lineno, co.co_name, sinfo)
            break
        return rv
    

提交回复
热议问题