Skip to content

Instantly share code, notes, and snippets.

@pirogoeth
Created October 25, 2019 21:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pirogoeth/b646b93d865bdf3b00e5ad2d3f12fb77 to your computer and use it in GitHub Desktop.
Save pirogoeth/b646b93d865bdf3b00e5ad2d3f12fb77 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
import inspect
def get_caller():
""" Inspects the call stack to determine the path of a caller.
Returns a string representing the full path to the caller.
"""
# If we want to get the "caller" of a function, from this context we
# must go backwards by two layers. The first frame is the current frame.
# The second frame would be the function that calls get_caller().
# The third frame is the frame we want to know the identity of.
# The named tuple, Traceback, looks like this:
# Traceback(filename, lineno, function, code_context, index)
frame = inspect.currentframe()
# Get a list of frames up to two outside of the current frame1.
callstack = inspect.getouterframes(frame, 2)
# callstack is [Traceback(...), ...]
# Grab the outermost frame
caller = callstack[2][0]
# Pull the Traceback tuple for the current frame.
callerinfo = inspect.getframeinfo(caller)
# Determine if the function is a bound method.
if 'self' in caller.f_locals:
# Since the caller is a bound method, extract the 'self' reference
# from the locals, then pull the class name from the instance class.
caller_class = caller.f_locals["self"].__class__.__name__
else:
# There is no object this method is bound to -- it is a module
# function.
caller_class = None
# Get the FQN of the module that the calling frame belongs to.
caller_module = inspect.getmodule(caller).__name__
# callerinfo is Traceback(...)
caller_name = callerinfo[2]
# Check the determined caller class.
if caller_class:
# If there is a caller class, prepend it to the caller name.
caller_string = f"{caller_class}.{caller_name}"
else:
# The caller string is just the caller name by itself.
caller_string = caller_name
# Check if we know the caller module.
if caller_module:
caller_string = f"{caller_module}.{caller_string}"
if caller.f_lineno:
caller_string = f"{caller_string}:{caller.f_lineno}"
return caller_string
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment