[Tutor] Getting caller name without the help of "sys._getframe(1).f_code.co_name" ?

Andreas Kostyrka andreas at kostyrka.org
Tue Feb 16 13:08:29 CET 2010


Am Samstag, 13. Februar 2010 16:56:08 schrieb patrice laporte:
> Hi,
> 
> Being in an exeption of my own, I want to print the name of the caller, and
> I'm looking for a way to have it.
> 
> I've found a lot of recipe all of them using what seems to be, according to
> me, a not so good trick : all those recipe make use of
> sys._getframe(1).f_code.co_name, such as in this exemple :
> 
> import sys
> 
> def whoami():
>    print "Who call me ? : ", sys._getframe(1).f_code.co_name
>    print "Who am I ? : ", sys._getframe(0).f_code.co_name
> 
> def print_caller_name():
>    whoami()
> 
> if __name__ == "__main__":
> 
>    print_caller_name()
> 
> With the following result, as expected  :
> 
> Who call me ? :  print_caller_name
> Who am I ? :  whoami
> 
> A closer look at the documentation about sys._getframe at
> http://docs.python.org/library/sys.html make me think it's not a good idea,
> because of the note :
> "*CPython implementation detail:* This function should be used for internal
> and specialized purposes only. *It is not guaranteed to exist in all
> implementations of Python*."
> 
> So, this trick works today, but what about tomorow ?

Well, the trick has worked for the better part of a decade.

If you need it (but there are probably better suited more specialized modules 
like traceback available), and you can live with the limitation to CPython, 
then use it.

Put differently, should the usage change, it will probably be for a very very 
good reason (and not before Python4, as Python3 does have a sys._getframe()).

Generally speaking, while sys._getframe does have a bad smell, a number of use 
cases come to mind which will probably assure it's existence eternally.
(e.g. accessing the class name space during definition of a class, which a ton 
of libraries, e.g. ORMs or probably zope.interface do use)

> Is anybody have an idea how to get the the same result without _getframe ?

Well, you've got basically the following options:

1.) sys._getframe
2.) sys._getframe hidden in a nicer API, e.g. traceback.
3.) manually (e.g. decorators, metaclasses, whatever) maintaining the "caller" 
site in your framework.
4.) use sys.settrace to maintain the caller site automatically (slow)
5.) use hotshot to log your execution to disc, and analyze that as needed.
6.) other obscure ideas that I forgot ;)

All of these can have their good reason, depending upon your requirements, and 
all of these are ugly in some way (and some of these incur a significant 
performance drop), so you need to decide why you need that stuff.

Another observation is that you'll probably want to isolate stuff like that in 
a small number of places, e.g. some top level loop that has to generally 
handle any exception (traceback would be your solution there, I guess), or 
some helper functions for some framework that do magic during class definition 
(getframe it is here I guess), or you need a general "sender" identity 
troughout your framework (then you'll go probably with some python constructs 
that maintain it manually/semi-automatically). And last but not least you 
might be debugging then settrace comes to mind.

But whatever you do it will probably be isolated to a small part of your 
source code.

Andreas


More information about the Tutor mailing list