[Python-Dev] getting at the current frame

Greg Ward gward@mems-exchange.org
Thu, 26 Oct 2000 12:03:09 -0400


On 24 October 2000, Barry A. Warsaw said:
> All well and good and doable in Python today, except getting the
> current frame with the exception raising trick is slooow.  A simple
> proposed addition to the sys module can improve the performance by
> about 8x:
> 
>     def _(s):
>         frame = sys.getcaller(1)
> 	d = frame.f_globals.copy()
> 	d.update(frame.f_locals())
> 	return the_translation_of(s) % d
> 
> The implementation of sys.getcaller() is given in the below patch.
> Comments?  I think this particular addition is too small for a PEP,
> although ?!ng still owns PEP 215 (which needs filling in).

+1.  Not sure if I would call that function 'getcaller()' or
'getframe()'; could go either way.

In my implementation of this (I guess everyone has one!), I also have a
couple of convenience functions:

  def get_caller_env (level=1):
      """get_caller_env(level : int = 1) -> (globals : dict, locals : dict)

      Return the environment of a caller: its dictionaries of global and
      local variables.  'level' has same meaning as for 'caller()'.
      """

  def get_frame_info (frame):
      """get_frame_info(frame)
         -> (filename : string,
             lineno : int,
             function_name : string,
             code_line : string)

      Extracts and returns a tuple of handy information from an execution
      frame.
      """

  def get_caller_info (level=1):
      """get_caller_info(level : int = 1)
         -> (filename : string,
             lineno : int,
             function_name : string,
             code_line : string)

      Extracts and returns a tuple of handy information from some caller's
      execution frame.  'level' is the same as for 'caller()', i.e.  if
      level is 1 (the default), gets this information about the caller of
      the function that is calling 'get_caller_info()'.
      """

These are mainly used by my unit-testing framework (which you'll no
doubt remember, Barry) to report where test failures originate.  Very
handy!

Looks like Ping's inspect.py has something like my 'get_frame_info()',
only it's called 'getframe()'.  Obviously this is the wrong name if
Barry's new function gets added as 'sys.getframe()'.  How 'bout this:

  sys.getframe(n)
    - return stack frame for depth 'n'
  inspect.getframeinfo(frame)
    - return (filename, line number, function name, lines-of-code)

Although I haven't grokked Ping's module enough to know if that rename
really fits his scheme.

        Greg
-- 
Greg Ward - software developer                gward@mems-exchange.org
MEMS Exchange / CNRI                           voice: +1-703-262-5376
Reston, Virginia, USA                            fax: +1-703-262-5367