Skip to content

Instantly share code, notes, and snippets.

@wware
Last active November 28, 2017 19:51
Show Gist options
  • Save wware/669819f930c3ac6000fd0cd466d00018 to your computer and use it in GitHub Desktop.
Save wware/669819f930c3ac6000fd0cd466d00018 to your computer and use it in GitHub Desktop.
Sometimes you want a Python function that includes a `logging.info()` or `logging.debug()` call, but you'd really prefer the logged filename and line number to be from the caller of your function, not your function itself. This is the solution to that problem, at least for Python 2.7. Also see https://stackoverflow.com/questions/12980512/custom-…
import os
import logging
from contextlib import contextmanager
logging.basicConfig(
format='%(asctime)-15s %(levelname)s %(filename)s:%(lineno)d %(message)s',
level=logging.INFO
)
def __LINE__():
callerframerecord = inspect.stack()[1]
frame = callerframerecord[0]
info = inspect.getframeinfo(frame)
return info.lineno
def findCaller(self):
f = logging.currentframe()
for _ in range(2 + logging._frame_delta):
if f is not None:
f = f.f_back
rv = "(unknown file)", 0, "(unknown function)"
while hasattr(f, "f_code"):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if filename == logging._srcfile:
f = f.f_back
continue
rv = (co.co_filename, f.f_lineno, co.co_name)
break
return rv
logging.Logger.findCaller = findCaller
logging._frame_delta = 0
@contextmanager
def logdelta(n):
d = logging._frame_delta
logging._frame_delta = d + n
yield
logging._frame_delta = d
def A(x):
with logdelta(1):
logging.info('A: ' + x) # Don't log with this line number
def B(x):
with logdelta(2):
logging.info('B: ' + x) # or with this line number
def C(x):
B(x) # or this line number
A('hello') # Instead, log with THIS line number
C('hello') # or THIS line number
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment