code python stack-trace introspection

code - Obtener__name__ del módulo de la función de llamada en Python



inspect python 3 (3)

Supongamos que myapp/foo.py contiene:

def info(msg): caller_name = ???? print ''[%s] %s'' % (caller_name, msg)

Y myapp/bar.py contiene:

import foo foo.info(''Hello'') # => [myapp.bar] Hello

Quiero que caller_name se establezca en el atributo __name__ del módulo de funciones de llamada (que es ''myapp.foo'') en este caso. ¿Cómo puede hacerse esto?


Confrontado con un problema similar, he encontrado que sys._current_frames () del módulo sys contiene información interesante que puede ayudarlo, sin la necesidad de importar inspeccionar, al menos en casos de uso específicos.

>>> sys._current_frames() {4052: <frame object at 0x03200C98>}

Luego puede "avanzar" usando f_back:

>>> f = sys._current_frames().values()[0] >>> # for python3: f = list(sys._current_frames().values())[0] >>> print f.f_back.f_globals[''__file__''] ''/base/data/home/apps/apricot/1.6456165165151/caller.py'' >>> print f.f_back.f_globals[''__name__''] ''__main__''

Para el nombre de archivo también puede usar f.f_back.f_code.co_filename, como sugiere Mark Roddy arriba. No estoy seguro de los límites y advertencias de este método (es probable que haya varios problemas) pero tengo la intención de usarlo en mi caso.


Mira el módulo de inspección:

inspect.stack() devolverá la información de la pila.

Dentro de una función, inspect.stack()[1] devolverá la pila de la persona que llama. Desde allí, puede obtener más información sobre el nombre de la función de la persona que llama, el módulo, etc.

Ver los documentos para más detalles:

http://docs.python.org/library/inspect.html

Además, Doug Hellmann tiene una buena reseña del módulo de inspección en su serie PyMOTW:

http://pymotw.com/2/inspect/index.html#module-inspect

EDITAR: Aquí hay un código que hace lo que quieres, creo:

def info(msg): frm = inspect.stack()[1] mod = inspect.getmodule(frm[0]) print ''[%s] %s'' % (mod.__name__, msg)


No recomiendo hacer esto, pero puede lograr su objetivo con el siguiente método:

def caller_name(): frame=inspect.currentframe() frame=frame.f_back.f_back code=frame.f_code return code.co_filename

Luego actualice su método existente de la siguiente manera:

def info(msg): caller = caller_name() print ''[%s] %s'' % (caller, msg)