108 votes

Obtenez __nom__ à l'appel de la fonction du module en Python

Supposons 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.foo] Hello

Je veux caller_name à être mis à l' __name__ attribut de l'appel de fonctions' module (qui est 'myapp.foo') dans ce cas. Comment cela peut-il être fait?

135voto

ars Points 35803

Découvrez les inspecter module:

inspect.stack() sera de retour, la pile de l'information.

L'intérieur d'une fonction, inspect.stack()[1] sera de retour à votre visiteur de la pile. À partir de là, vous pouvez obtenir plus d'informations sur l'appelant du nom de la fonction, du module, etc.

Voir la documentation pour plus de détails:

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

Aussi, Doug Hellmann a une belle description de l'inspecter le module dans son PyMOTW de la série:

http://blog.doughellmann.com/2007/11/pymotw-inspect.html

EDIT: Voici un bout de code qui fait ce que vous voulez, je pense que:

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

22voto

Louis LC Points 813

Confronté à un problème similaire, j'ai trouvé que sys._current_frames() du module sys contient des informations utiles qui peuvent vous aider, sans la nécessité d'importer de l'inspecter, au moins dans des cas d'utilisation spécifiques.

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

Vous pouvez ensuite "monter" à l'aide de f_back :

>>> f = 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 la Marque de Roddy ci-dessus. Je ne suis pas sûr de l'limites et mises en garde de cette méthode (plusieurs threads vont probablement être un problème), mais j'ai l'intention de l'utiliser dans mon cas.

3voto

Mark Roddy Points 7568

Je ne recommande pas de le faire, 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

Puis mise à jour de votre méthode comme suit:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X