0

I'm working on a tool to visualize Python profile traces, and to do that, it would be useful to know what line a function is called from.

Suppose I have the following simple program:

import time

def my_sleep(x):
  time.sleep(x)

def main():
  my_sleep(1)
  my_sleep(2)

main()

If I run cProfile on it (python -m cProfile -o a.data a.py), I get a marshaled file containing the following data structure:

 ('a.py', 3, 'my_sleep'): (2,
                           2,
                           1.4999999999999999e-05,
                           3.00576,
                           {('a.py', 6, 'main'): (2,
                                                  2,
                                                  1.4999999999999999e-05,
                                                  3.00576)}),

Essentially, this says that my_sleep() is called twice by main() on line 6, and this adds up to slightly over 3 seconds.

Is there any way to find out what line it's being called from, and not just what function? So in this case, my_sleep() is called on line 7 for 1 second, and line 8 for 2 seconds.

martineau
  • 119,623
  • 25
  • 170
  • 301
Bai Li
  • 1,108
  • 1
  • 16
  • 25
  • Your output doesn't look like the example output in the Python docs. Are you doing some other formatting to it? https://docs.python.org/3.3/library/profile.html#instant-user-s-manual – Patrick Haugh Sep 23 '16 at 18:55
  • Yes, I'm saving it as a marshaled file (`-o a.data`) and loading it in the python interpreter (`marshal.load(open('a.data'))`), then put it through pprint. – Bai Li Sep 23 '16 at 19:25
  • Have you tried looking at the output printed on the console, without saving the file? – Patrick Haugh Sep 23 '16 at 19:28
  • There's a tool called the [line profiler](https://pypi.python.org/pypi/line_profiler) you might find helpful. – martineau Sep 23 '16 at 20:52
  • If you put a sleep in your function, [*this will do the job*](http://stackoverflow.com/a/4299378/23771). – Mike Dunlavey Sep 26 '16 at 12:16

1 Answers1

0

You may use sys._getframe(1) in order to know the caller like so:

import sys

def my_sleep():
    print("Line #" + str(sys._getframe(1).f_lineno))
    time.sleep(x)

Keep in mind doing things like that are usually not encouraged but if it's just temporary that's fine I guess.

Bharel
  • 23,672
  • 5
  • 40
  • 80
  • Hmm ok. I'm working with a large codebase though, and I don't want to put a print statement in every function. – Bai Li Sep 23 '16 at 19:27