Supposons qu'il myapp/foo.py
contienne:
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 veux caller_name
être défini sur l' __name__
attribut du module des fonctions appelantes (qui est «myapp.foo») dans ce cas. Comment cela peut-il être fait?
python
stack-trace
introspection
Sridhar Ratnakumar
la source
la source
caller_name
ne peut donc pas l'être__main__
Réponses:
Découvrez le module d'inspection:
inspect.stack()
renverra les informations de pile.À l'intérieur d'une fonction,
inspect.stack()[1]
retournera 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.Consultez la documentation pour plus de détails:
http://docs.python.org/library/inspect.html
De plus, Doug Hellmann a une belle description du module d'inspection de 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:
la source
__name__
attribut de ce module en utilisant leinspect
module? Par exemple, comment puis-je revenirmyapp.foo
(pasmyapp/foo.py
) dans mon exemple ci-dessus? J'ai déjà essayé d'utiliser le module inspect avant de poster chez SO.inspect.stack()[2]
pour l'appelant réel.Confronté à 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 inspect, du moins dans des cas d'utilisation spécifiques.
Vous pouvez ensuite "monter" en utilisant f_back:
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.
la source
sys._getframe(1)
, au lieu d'appelersys._current_frames()
(btw qui renvoie un mappage de trame pour chaque thread).inspect.currentframe()
au lieu desys._current_frames().values()[0]
.Je ne recommande pas de faire cela, mais vous pouvez atteindre votre objectif avec la méthode suivante:
Ensuite, mettez à jour votre méthode existante comme suit:
la source
__name__