2012-08-03 16 views
7

Deseo obtener información sobre los llamadores de una función específica en python. Por ejemplo:Obtener información de las personas que llaman en python

class SomeClass(): 
    def __init__(self, x): 
     self.x = x 
    def caller(self): 
     return special_func(self.x) 

def special_func(x): 
    print "My caller is the 'caller' function in an 'SomeClass' class." 

¿Es posible con python?

Respuesta

10

Sí, la función sys._getframe() vamos a recuperar los marcos de la pila de ejecución actual, que luego se puede inspeccionar con los procedimientos y la documentación se encuentran en el inspect module; se le busca para los locales específicos en el atributo f_locals, así como para la información f_code:

import sys 
def special_func(x): 
    callingframe = sys._getframe(1) 
    print 'My caller is the %r function in a %r class' % (
     callingframe.f_code.co_name, 
     callingframe.f_locals['self'].__class__.__name__) 

Tenga en cuenta que tendrá que tomar un cierto cuidado para detectar qué tipo de información que se encuentra en cada cuadro.

+2

A partir de los documentos: 'No está garantizado que existen en todas las implementaciones de Python.' – pradyunsg

3

Un ejemplo:

def f1(a): 
    import inspect 
    print 'I am f1 and was called by', inspect.currentframe().f_back.f_code.co_name 
    return a 

def f2(a): 
    return f1(a) 

recuperará la persona que llama "inmediata".

>>> f2(1) 
I am f1 and was called by f2 

Y si no se llamaba de otra te dan (en reposo):

>>> f1(1) 
I am f1 and was called by <module> 
+0

Gracias, Pude tomar esto y adaptarlo a mis necesidades. –

2

Gracias a la respuesta de Jon Clements yo era capaz de hacer una función que devuelve una lista ordenada de todas las personas que llaman:

def f1(): 
    names = [] 
    frame = inspect.currentframe() 
    ## Keep moving to next outer frame 
    while True: 
     try: 
      frame = frame.f_back 
      name = frame.f_code.co_name 
      names.append(name) 
     except: 
      break 
    return names 

y cuando se le llama en una cadena:

def f2(): 
    return f1() 

def f3(): 
    return f2() 

def f4(): 
    return f3() 

print f4() 

se parece a esto:

['f2', 'f3', 'f4', '<module>'] 

En mi caso puedo filtrar a cabo nada en '<module>' y después, y luego tomar el último elemento a ser el nombre de la persona que llama de origen.

o modificar la secuencia original para rescatar a la primera aparición de cualquier nombre que comienza con '<':

frame = frame.f_back 
name = frame.f_code.co_name 
if name[0] == '<': 
    break 
names.append(name) 
Cuestiones relacionadas