Python: how to get the *full* name of the function I am in
Asked Answered
A

2

9

Is there a way so that the following code:

import traceback

def log(message):
    print "%s: %s" %(traceback.extract_stack()[0:-1][-1][2], message)

def f1():
    log("hello")

class cls(object):
    def f1(self):
        log("hi there")

f1()
mycls = cls()
mycls.f1()

displays:

f1: hello
cls.f1: hi there

instead of:

f1: hello
f1: hi there

?

I tried to use module 'inspect' but was not successful...

Julien

EDIT:

The point here is for 'log' function to be able to retrieve its caller name on its own (using traceback, inspect, or any mean necessary).

I do not want to pass the class name, or anything else than 'message' to the 'log' function.

Audiology answered 2/8, 2017 at 20:25 Comment(10)
Can you use __qualname__?Saretta
#10973862Balcer
@Saretta given the python2.x syntax in the question I'd guess not?Rickettsia
@AnthonySottile -- Yeah, I was just coming to that conclusion myself -- though there is an (imperfect) substitute on pypi (pypi.python.org/pypi/qualname)Saretta
@AnthonySottile -- Also, from frame objects, I don't think you actually have a reference back to the function object -- Only it's name.Saretta
@Saretta indeed, there's f_code but that's only the code object (a function object contains code + some other things)Rickettsia
@Saretta holy hell: "This module uses source code inspection to figure out how (nested) classes and functions are defined in order to determine the qualified names for them. That means parsing the source file, and traversing the AST (abstract syntax tree). This sounds very hacky, and it is, but the Python interpreter itself does not have the necessary information, so this justifies extreme measures."Larvicide
@everyone: yes, as of today, I use python 2.7.12 (default python on Ubuntu 16.04.2). Would python3 allow me to do what I need?Audiology
@JulienREINAULD: In your question "displays" and "instead of" are swapped, isn't it?Chuchuah
@LaurentLAPORTE Hum I don't think so. I wish the full name instead of the leaf nameAudiology
A
2

So I finally came up this method:

#!/usr/bin/env python3

def log(message):
    import inspect
    import gc
    code = inspect.currentframe().f_back.f_code
    func = [obj for  obj in  gc.get_referrers(code) if inspect.isfunction(obj)][0]
    print(func.__qualname__, message)

It needs python3 so that __qualname__ can be used.

Audiology answered 25/8, 2017 at 13:1 Comment(0)
M
-1

The inspect module is very powerful, and can be used in a similar fashion to the way you use traceback to get the name of the function, and probably also the class name. But you can simply make use of the fact that you have the self instance variable, which knows of its own type/class:

import inspect

class cls(object):
    def f1(self):
        this_class_name = type(self).__name__
        this_func_name = inspect.currentframe().f_code.co_name
        print(this_class_name, this_func_name)

mycls = cls()
mycls.f1()
Misquotation answered 2/8, 2017 at 20:47 Comment(1)
You are correct. However, what I am really trying to achieve (sorry I did not asked that explicitely in my question) is to retrieve the class name from traceback, without the need to pass it as an argument to my 'log' function.Audiology

© 2022 - 2024 — McMap. All rights reserved.