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)