2009-05-22 2 views
74

Se si dispone di 2 funzioni come:Ottenere il nome della funzione del chiamante all'interno di un'altra funzione in Python?

def A 
def B 

e A chiama B, si può ottenere che chiama B all'interno B, come:

def A() : 
    B() 

def B() : 
    this.caller.name 
+1

Hai la fonte disponibile. Perché avresti bisogno di una cosa del genere? –

+12

Perché eseguo il debug del codice nell'interprete python di un'applicazione di terze parti in cui non è presente un debugger reale. –

+3

possibile duplicato di [Python: come ottenere il nome del metodo del chiamante nel metodo chiamato?] (Http://stackoverflow.com/questions/2654113/python-how-to-get-the-callers-method-name-in -the-called-method) – bernie

risposta

103

È possibile utilizzare il modulo inspect per ottenere la chiamata pila. Restituisce una lista di record di frame. Il terzo elemento in ogni record è il nome del chiamante. Quello che vuoi è questo:

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

Naturalmente, è una buona idea per controllare che sufficiente telaio esistono record prima di tentare di accedere ad un determinato indice.

+6

su python 3.4 almeno questo non funziona, hanno cambiato l'ordine delle tuple. Viene ora utilizzata una tupla denominata, quindi è meglio usare inspect.stack() [1] .filename – timeyyy

8

come nell'esempio seguente:

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

Importante: come è evidente dal nome _getframe metodo (Hey, inizia con un trattino), non è un metodo API uno dovrebbe essere sconsideratamente basano su .

+9

[sys._getframe] (http://docs.python.org/library/sys.html#sys._getframe) è "Non è garantito che esista in tutte le implementazioni di Python" - Penso che sia importante notare. – RWS

+0

@ RWS, grazie, indicato –

2

è possibile all'utente il modulo di registrazione e specificare il% (filename) s opzione 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

Inavvertitamente si dice "% (nome file) s opzione". Dovrebbe essere quello che hai nel tuo esempio di codice: '% (funcName) s' :) –

10

Ci sono due modi, utilizzando sys e inspect moduli:

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

La forma stack() è meno leggibile e dipende dall'implementazione perché chiama sys._getframe(), vedi estratto 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) 
4

Questo funziona per me! : D

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