I have an awesome little function that looks like this:
def verbose_print(message, *args, **kwargs):
"""Prints `message` with a helpful prefix when in verbose mode
Args:
message (str): The message to print. Can be a format string, e.g.
`A %s with some %s in it`
*args: Variables for the message format
**kwargs: Keyword variables for the message format
"""
# Only print when in verbose mode
if not config.verbose:
return
# Ready a prefix for the message
try:
s = inspect.stack()
module_name = inspect.getmodule(s[1][0]).__name__
func_name = s[1][3]
prefix = '### %s->%s' % (module_name, func_name)
except Exception as e:
prefix = '### [stack unavailable]'
if args:
message = message % args
elif kwargs:
message = message % kwargs
print '%s: %s' % (prefix, message)
The point of the function is that I can call it from anywhere with a message, and if my project config file is set to verbose mode, all the messages will be printed with a helpful prefix to show where it was called. Here's an example of some output:
### avesta.webserver->check_login: Checking login for client at 127.0.0.1 ### avesta.webserver->check_login: Found credentials cookie with username: tomas, token: blablabla ### avesta.webserver->check_login: Login valid, refreshing session ### avesta.webserver->get_flash_memory: Fetched flash data: None ### avesta.webserver->get: Fetched data from empty path ('previous_values', 'name'), returning '' ### avesta.webserver->get: Fetched data from empty path ('previous_values', 'description'), returning '' ### avesta.webserver->get: Fetched data from empty path ('validation_errors', 'name'), returning ''
The format is "### module->function: message".
Now most of the time this is really helpful, but it's not perfect. In the example above, the "get" function is actually a bound method of a class, but that's not visible. What I'm trying to accomplish is that when a function is a bound method, I print with this format instead:
"### module->ClassName.function"
But the problem is:
Thanks for any answers that can help me figure this out.
I thought this was going to be easy, but it turned out to be a bit complicated. If you have a reference to the bound method, you can get its class name via boundMethod.im_class.__name__
. However, when you're grabbing the stack, you can't easily get a reference to the bound method, just to stack frames.
However all is not lost! The inspect
module can get you function arguments from a stack frame using the getargvalues
function. You do have to cheat a little, by relying on the convention that methods always have their first argument named "self". You can check for that, then grab the "self" value from the function's locals
dict, and from there it's easy to get the class name. Try replacing your current try
block with his code:
s = inspect.stack()
module_name = inspect.getmodule(s[1][0]).__name__
func_name = s[1][3]
arginfo = inspect.getargvalues(s[1][0])
if len(arginfo.args) > 0 and arginfo.args[0] == "self":
func_name = "%s.%s" (arginfo.locals["self"].__class__.__name__, func_name)
prefix = '### %s->%s' % (module_name, func_name)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With