174 votes

Obtenir le nom de la fonction appelante dans une autre fonction en Python ?

Si vous avez 2 fonctions comme :

def A
def B

et A appelle B, pouvez-vous obtenir qui appelle B à l'intérieur de B, comme :

def A () :
    B ()

def B () :
    this.caller.name

1 votes

Vous avez la source disponible. Pourquoi auriez-vous besoin d'une telle chose ?

39 votes

Parce que je débogue le code dans l'interpréteur python d'une application tierce où il n'y a pas de véritable débogueur.

0 votes

265voto

Ayman Hourieh Points 39435

Vous pouvez utiliser le inspecter pour obtenir les informations souhaitées. Son pile renvoie une liste d'enregistrements de cadres.

  • Pour Python 2 chaque enregistrement de trame est une liste. Le troisième élément de chaque enregistrement est le nom de l'appelant. Voici ce que vous voulez :

    >>> import inspect
    >>> def f():
    ...     print inspect.stack()[1][3]
    ...
    >>> def g():
    ...     f()
    ...
    >>> g()
    g

  • Pour Python 3.5 et plus chaque enregistrement de trame est un tuple nommé vous devez donc remplacer

    print inspect.stack()[1][3]

    avec

    print(inspect.stack()[1].function)

    sur le code ci-dessus.

15 votes

Sur python 3.4 au moins, cela ne fonctionne pas, ils ont changé l'ordre des tuples. Un tuple nommé est maintenant utilisé, il est donc préférable d'utiliser inspect.stack()[1].filename

6 votes

En fait, vous voulez probablement inspect.currentframe().f_back.f_code.co_name qui est indépendant de la version ou de l'implémentation de Python.

0 votes

@1313e : aussi inspect.currentframe() dépend de l'implémentation de Python, puisque si vous lisez le code source de inspect.py ils utilisent tous deux sys._getframe()

37voto

Eric Points 21

Il y a deux façons de procéder, en utilisant sys y inspect modules :

  • sys._getframe(1).f_code.co_name
  • inspect.stack()[1][3]

En stack() est moins lisible et dépend de l'implémentation puisqu'elle appelle sys._getframe() voir l'extrait de inspect.py :

def stack(context=1):
    """Return a list of records for the stack above the caller's frame."""
    return getouterframes(sys._getframe(1), context)

16voto

Piotr Findeisen Points 1712

Note (juin 2018) : aujourd'hui, j'utiliserais probablement . inspect module, voir les autres réponses

sys._getframe(1).f_code.co_name comme dans l'exemple ci-dessous :

>>> def foo():
...  global x
...  x = sys._getframe(1)
...
>>> def y(): foo()
...
>>> y()
>>> x.f_code.co_name
'y'
>>>  

Note importante : comme il est évident dans l'image de l _getframe (hé, ça commence par un trait de soulignement), il ne s'agit pas d'une méthode de l'API à laquelle il faut se fier sans réfléchir.

14 votes

sys._getframe n'est "pas garanti d'exister dans toutes les implémentations de Python" - je pense que c'est important à noter.

9voto

Alex Cory Points 389

Cela fonctionne pour moi ! :D

>>> def a():
...     import sys
...     print sys._getframe(1).f_code.co_name
...
>>> def b():
...     a()
...
...
>>> b()
b
>>>

5voto

mescalin Points 111

Vous pouvez utiliser le module de journalisation et spécifier l'option %(funcName)s dans BaseConfig()

import logging
logging.basicConfig(filename='/tmp/test.log', level=logging.DEBUG, format='%(asctime)s | %(levelname)s | %(funcName)s |%(message)s')

def A():
    logging.info('info')

1 votes

Vous dites par inadvertance %(filename)s option . Cela devrait être ce que vous avez dans votre exemple de code : %(funcName)s :)

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