I’ve been using cProfile to profile my code, and it’s been working great. I also use gprof2dot.py to visualize the results, which helps clarify things.
However, cProfile (and most other Python profilers I’ve seen so far) only profiles at the function-call level. This leads to confusion when certain functions are called from different places, as I can’t tell if call #1 or call #2 is taking up the majority of the time. This issue worsens when the function is deep in the call stack and called from multiple places.
How can I achieve line-by-line profiling?
Instead of this:
function #12, total time: 2.0s
I’d like to see something like this:
function #12 (called from somefile.py:102) 0.5s
function #12 (called from main.py:12) 1.5s
cProfile shows how much of the total time “transfers” to the parent, but this connection is lost when you have many layers and interconnected calls.
Ideally, I’d love a GUI that parses the data and shows me my source file with the total time given to each line. Something like this:
main.py:
a = 1 # 0.0s
result = func(a) # 0.4s
c = 1000 # 0.0s
result = func(c) # 5.0s
Then, I’d be able to click on the second “func(c)” call to see what’s happening.
The line_profiler module is specifically designed for line-by-line profiling of Python code. It gives detailed statistics about the time spent on each individual line within a function.
Install the line_profiler package:
pip install line_profiler
Use the @profile decorator to mark functions you want to profile:
from line_profiler import LineProfiler
def my_function(a, b):
result = a + b # Line 1
c = a * b # Line 2
return result + c
# Profile the function
profiler = LineProfiler()
profiler.add_function(my_function)
profiler.run('my_function(5, 10)')
profiler.print_stats()
The line_profiler will show the time spent on each line of my_function, similar to:
Timer unit: 1e-06 s
Total time: 0.000234 s
Function: my_function at line 3
0.000123 0.000123 1 1 result = a + b
0.000111 0.000111 1 1 c = a * b
cProfile can also be used to generate profiling data, which can then be visualized line-by-line using a tool like SnakeViz.
Profile your code with cProfile:
import cProfile
def my_function(a, b):
result = a + b
c = a * b
return result + c
cProfile.run('my_function(5, 10)', 'profile_stats')
Use SnakeViz to visualize the profiling data:
pip install snakeviz
Run SnakeViz:
snakeviz profile_stats
This will launch a GUI that visualizes profiling results, helping you view which lines are consuming the most time. It may not be as granular as line_profiler, but it gives you a broader understanding of where time is spent.
py-spy is a sampling profiler for Python that can track the execution of Python programs, including visualizing call stacks and time spent on specific lines.
Install py-spy:
pip install py-spy
Run py-spy to attach to a running Python process and view the profiling information:
py-spy top --pid <PID>
Use the py-spy graphical interface to view the line-by-line breakdown of execution.
This solution provides a real-time, interactive way to monitor and profile Python code with a GUI, offering insight into execution time at a fine-grained level.