290 votes

Comment obtenir le nom de la méthode de l'appelant dans la méthode appelée ?

Python : Comment obtenir le nom de la méthode de l'appelant dans la méthode appelée ?

Supposons que j'ai 2 méthodes :

def method1(self):
    ...
    a = A.method2()

def method2(self):
    ...

Si je ne veux pas faire de changement pour la méthode1, comment obtenir le nom de l'appelant (dans cet exemple, le nom est méthode1) dans la méthode2 ?

7 votes

14voto

migpok35 Points 576

C'est un peu un amalgame de ce qui précède. Mais voici mon essai.

def print_caller_name(stack_size=3):
    def wrapper(fn):
        def inner(*args, **kwargs):
            import inspect
            stack = inspect.stack()

            modules = [(index, inspect.getmodule(stack[index][0]))
                       for index in reversed(range(1, stack_size))]
            module_name_lengths = [len(module.__name__)
                                   for _, module in modules]

            s = '{index:>5} : {module:^%i} : {name}' % (max(module_name_lengths) + 4)
            callers = ['',
                       s.format(index='level', module='module', name='name'),
                       '-' * 50]

            for index, module in modules:
                callers.append(s.format(index=index,
                                        module=module.__name__,
                                        name=stack[index][3]))

            callers.append(s.format(index=0,
                                    module=fn.__module__,
                                    name=fn.__name__))
            callers.append('')
            print('\n'.join(callers))

            fn(*args, **kwargs)
        return inner
    return wrapper

Utilisez :

@print_caller_name(4)
def foo():
    return 'foobar'

def bar():
    return foo()

def baz():
    return bar()

def fizz():
    return baz()

fizz()

La sortie est

level :             module             : name
--------------------------------------------------
    3 :              None              : fizz
    2 :              None              : baz
    1 :              None              : bar
    0 :            __main__            : foo

4 votes

Cela déclenchera un IndexError si la profondeur de pile demandée est supérieure à la profondeur réelle. Utilisez modules = [(index, inspect.getmodule(stack[index][0])) for index in reversed(range(1, min(stack_size, len(inspect.stack()))))] pour obtenir les modules.

0 votes

Merci beaucoup pour cela. Je suggérerais de rassembler les modules un peu différemment, par exemple : modules = [(index, module) for index in reversed(range(1, min(stack_size, len(stack)))) if index and (module := inspect.getmodule(stack[index][0]))] . De cette façon, vous pouvez vous assurer que vous n'aurez pas None dans vos autres listes. Je pense également qu'il est bon d'ajouter module_name_lengths.append(len(func.__module__)) car le formatage ne tient pas compte de l'élément le plus bas dans le tableau.

0 votes

Dans cette solution, nous devrions aussi probablement return fn(*args, **kwargs) car la solution actuelle supprime les retours des fonctions décorées et les casse.

1voto

#!/usr/bin/env python
import inspect

called=lambda: inspect.stack()[1][3]

def caller1():
    print "inside: ",called()

def caller2():
    print "inside: ",called()

if __name__=='__main__':
    caller1()
    caller2()
shahid@shahid-VirtualBox:~/Documents$ python test_func.py 
inside:  caller1
inside:  caller2
shahid@shahid-VirtualBox:~/Documents$

2 votes

called() est la fonction qui a été appelée mais pas la fonction qui fait l'appel de callerN()

0voto

Michael Swartz Points 48

J'ai trouvé un moyen si vous traversez des classes et que vous voulez la classe à laquelle la méthode appartient ET la méthode. Cela demande un peu de travail d'extraction, mais c'est efficace. Cela fonctionne dans Python 2.7.13.

import inspect, os

class ClassOne:
    def method1(self):
        classtwoObj.method2()

class ClassTwo:
    def method2(self):
        curframe = inspect.currentframe()
        calframe = inspect.getouterframes(curframe, 4)
        print '\nI was called from', calframe[1][3], \
        'in', calframe[1][4][0][6: -2]

# create objects to access class methods
classoneObj = ClassOne()
classtwoObj = ClassTwo()

# start the program
os.system('cls')
classoneObj.method1()

-1voto

Freezy Points 15

Hé mec, j'ai déjà fait 3 méthodes sans plugins pour mon application et peut-être que ça peut t'aider, ça a marché pour moi donc peut-être que ça va marcher pour toi aussi.

def method_1(a=""):
    if a == "method_2":
        print("method_2")

    if a == "method_3":
        print("method_3")

def method_2():
    method_1("method_2")

def method_3():
    method_1("method_3")

method_2()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X