1

I have the following scenario, where I want to get frame info for the scope above my scope.

def outer():
    # This is really slow.
    frames = inspect.stack()

    def inner():
        # I would like to "pay for it" here instead.
        print(frames)

    return inner

The call inspect.stack() is very slow, so I would like to do it only when I really need to, meaning when someone calls inner. But if I move it inside the inner function, I would get different frames than what I need.

Alternatively if I could get all of frame.filename and frame.lineno, (for each frame for the outer scope), fast in some other way - that is also good.

Uri
  • 25,622
  • 10
  • 45
  • 72

1 Answers1

1

There's no way to delay the work until the inner call, because the information you want doesn't exist any more at that point. If you try to delay the work until inner, you'll only be able to retrieve information about the state of the program at the time of the inner call, which will be a completely different state than at the time of the outer call.

That said, inspect.stack is pretty slow, and you only care about file name and line number information. inspect.stack is doing a lot of work you don't want. If all you want is file name and line number information, you can use traceback.extract_stack, which should be a lot faster.

You can go even faster by extracting the information you want manually:

def do_it_manually():
    frame = inspect.currentframe().f_back
    results = []
    while frame:
        results.append((frame.f_code.co_filename, frame.f_lineno))
        frame = frame.f_back
    return results

This gives a list of (filename, lineno) tuples, starting from do_it_manually's caller. It's several orders of magnitude faster than inspect.stack when I test it with a deep stack.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • This is great, thanks! also if you're interested this is what I'm using it for: https://github.com/hyroai/gamla/pull/113 – Uri Mar 29 '21 at 03:07