Line-by-line profiler
line_profiler is a module for doing line-by-line profiling of functions, providing detailed timing statistics for each line within selected functions. kernprof is a companion script that conveniently runs line_profiler or Python's standard library profilers. It is currently at version 5.0.2 and actively maintained, with a release cadence that includes regular bug fixes and feature enhancements.
Warnings
- breaking Python 3.6 and 3.7 support was removed in version 4.2.0. Users on these Python versions must use an older version of line-profiler or upgrade their Python interpreter.
- breaking Version 5.0.0 introduced potential speed regressions (fixed in 5.0.1) and specifically had issues with 'duplicate or inconsistent profiler output under Python 3.14 when multiprocessing is used.' This was fixed in 5.0.1.
- gotcha Profiling inherently adds overhead to your code's execution. The measured times reflect the profiled execution, not necessarily the exact performance without profiling. Be mindful of this when interpreting results.
- gotcha line_profiler may produce unexpected or no results when profiling multi-threaded, multi-processing, or asynchronous (asyncio) code due to the nature of its tracing mechanism.
- gotcha For programmatic control, directly calling `profiler.enable()` and `profiler.disable()` can be unsafe when nested. If you need nested profiling, use `profiler.enable_by_count()` and `profiler.disable_by_count()` instead.
- gotcha When profiling Cython extensions built with relative paths, `line_profiler` might fail to display the original source code along with profiling results.
Install
-
pip install line-profiler -
pip install line-profiler[all]
Imports
- profile
from line_profiler import profile
- LineProfiler
from line_profiler import LineProfiler
Quickstart
import time
from line_profiler import profile
import os
@profile
def slow_function_one():
time.sleep(0.01)
[x * x for x in range(1000)] # This line will be profiled
@profile
def slow_function_two(iterations):
data = []
for _ in range(iterations):
data.append(sum(range(100)))
time.sleep(0.02)
def main():
print('Starting profiling demo...')
slow_function_one()
slow_function_two(1000)
print('Profiling demo finished.')
if __name__ == '__main__':
# Method 1: Run with environment variable (requires line_profiler to be imported and decorated)
# To run: LINE_PROFILE=1 python my_script.py
# Output will be printed to console and .lprof file generated.
# Method 2: Run directly via kernprof CLI (recommended for explicit control)
# To run: kernprof -lvr my_script.py
# -l enables line-by-line profiling
# -v prints results to stdout
# -r enables rich output (if 'rich' is installed)
# This block ensures the script is runnable even without explicit kernprof or env var
if os.environ.get('LINE_PROFILE') == '1':
main()
else:
# For direct execution without profiling enabled, or if kernprof handles execution
main()