Supposons que myapp/foo.py
contient:
def info(msg):
caller_name = ????
print '[%s] %s' % (caller_name, msg)
Et myapp/bar.py
contient:
import foo
foo.info('Hello') # => [myapp.bar] Hello
Je voudrais caller_name
à définir sur __name__
attribut du module des fonctions appelantes (qui est 'myapp.foo') dans ce cas. Comment cela peut-il être fait?
Découvrez le module d'inspection:
inspect.stack()
renverra les informations de la pile.
Dans une fonction, inspect.stack()[1]
renverra la pile de votre appelant. De là, vous pouvez obtenir plus d'informations sur le nom de la fonction de l'appelant, le module, etc.
Voir les documents pour plus de détails:
http://docs.python.org/library/inspect.html
De plus, Doug Hellmann a une belle synthèse du module d'inspection dans sa série PyMOTW:
http://pymotw.com/2/inspect/index.html#module-inspect
EDIT: Voici un code qui fait ce que vous voulez, je pense:
def info(msg):
frm = inspect.stack()[1]
mod = inspect.getmodule(frm[0])
print '[%s] %s' % (mod.__name__, msg)
Face à un problème similaire, j'ai trouvé que sys._current_frames () du module sys contient des informations intéressantes qui peuvent vous aider, sans avoir besoin d'importer inspecter, au moins dans des cas d'utilisation spécifiques.
>>> sys._current_frames()
{4052: <frame object at 0x03200C98>}
Vous pouvez ensuite "remonter" en utilisant 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__'
Pour le nom de fichier, vous pouvez également utiliser f.f_back.f_code.co_filename, comme suggéré par Mark Roddy ci-dessus. Je ne suis pas sûr des limites et des mises en garde de cette méthode (plusieurs threads seront probablement un problème) mais j'ai l'intention de l'utiliser dans mon cas.
Je ne recommande pas cela, mais vous pouvez atteindre votre objectif avec la méthode suivante:
def caller_name():
frame=inspect.currentframe()
frame=frame.f_back.f_back
code=frame.f_code
return code.co_filename
Mettez ensuite à jour votre méthode existante comme suit:
def info(msg):
caller = caller_name()
print '[%s] %s' % (caller, msg)