cProfile module
Overview
cProfile is a C extension module that provides deterministic profiling for Python code. It is based on lsprof and has much lower overhead than the pure Python profile module, making it suitable for profiling long-running programs.
The module ships with the standard library, so no installation is required. Use cProfile when you need to understand where your code spends its time.
Quick Start
The fastest way to profile a piece of code is with cProfile.run():
import cProfile
cProfile.run('re.compile("foo|bar")')
This prints profile output showing function call counts, timing data, and source locations. By default, output is sorted by standard name ('stdname').
The Profile Class
For more control, instantiate Profile directly:
import cProfile
pr = cProfile.Profile()
pr.enable()
# ... code you want to profile ...
pr.disable()
pr.print_stats()
Key Methods
| Method | Description |
|---|---|
enable() | Start collecting profiling data |
disable() | Stop collecting profiling data |
create_stats() | Stop collecting and record results internally |
print_stats(sort=-1) | Create a Stats object and print to stdout |
dump_stats(filename) | Write profile data to a file |
runcall(func, *args, **kwargs) | Profile a single function call |
runctx(cmd, globals, locals) | Profile code with explicit namespace dicts |
Context Manager
Python 3.8 introduced context manager support:
import cProfile
with cProfile.Profile() as pr:
result = some_function()
pr.print_stats()
This ensures profiling is always stopped, even if an exception occurs.
Saving and Analyzing Profile Data
To save profile output to a file for later analysis:
import cProfile
cProfile.run('some_function()', 'profile.out')
Load that file with pstats.Stats:
import pstats
from pstats import SortKey
ps = pstats.Stats('profile.out')
ps.strip_dirs() # remove leading paths from filenames
ps.sort_stats(SortKey.TIME)
ps.print_stats(10) # top 10 lines
Merging Profile Runs
You can combine multiple profile files:
ps = pstats.Stats('profile1.out')
ps.add('profile2.out')
ps.print_stats()
Inspecting Callers and Callees
To see which functions called a specific function:
ps.print_callers('my_function')
To see what a function called:
ps.print_callees('my_function')
Sort Options
Import sort keys from pstats:
from pstats import SortKey
| String | SortKey | What it sorts |
|---|---|---|
'time' | SortKey.TIME | Internal time (excludes subfunction time) |
'cumulative' | SortKey.CUMULATIVE | Cumulative time in function + subfunctions |
'calls' | SortKey.CALLS | Call count |
'pcalls' | SortKey.PCALLS | Primitive call count (excludes recursive) |
'name' | SortKey.NAME | Function name |
'filename' | SortKey.FILENAME | File name |
'stdname' | SortKey.STDNAME | Standard name (default sort) |
Multi-level sorting is supported by passing a tuple:
ps.sort_stats(SortKey.TIME, SortKey.CUMULATIVE)
Numeric Sort Codes (Legacy)
For backward compatibility, numeric values still work: -1 = stdname, 0 = calls, 1 = time, 2 = cumulative.
Output Columns
The profile table contains these columns:
| Column | Meaning |
|---|---|
ncalls | Number of calls (shown as total/primitive for recursive functions) |
tottime | Time spent in the function, excluding subfunction calls |
percall (tottime) | tottime / ncalls |
cumtime | Cumulative time in the function + all subfunctions |
percall (cumtime) | cumtime / primitive_calls |
filename:lineno(function) | Source location and function name |
Command-Line Usage
Profile an entire script from the terminal:
python -m cProfile -s cumulative myscript.py
Save output to a file:
python -m cProfile -o profile.out -s time myscript.py
Launch an interactive browser:
python -m pstats profile.out
Profile a module instead of a script:
python -m cProfile -m mymodule arg1 arg2
Limitations
A few things to keep in mind when using cProfile:
Clock resolution is ~0.001 seconds. Timing accuracy is limited to this granularity. For precise benchmarks, use timeit instead.
The profiler adds overhead to Python code but not C functions. This makes C code appear proportionally faster than it actually is. Results are useful for relative comparisons within Python code, not absolute measurements.
Profile files are not portable across Python versions or operating systems. Do not rely on compatibility when sharing profile data.
The default sort is 'stdname', not 'cumulative'. Many users expect cumulative time by default and find this surprising.
See Also
- /reference/modules/sys-module/ — Inspect Python’s runtime environment and interpreter state
- /reference/modules/timeit-module/ — Measure small code snippets for performance benchmarking
- /reference/modules/dis-module/ — Inspect Python bytecode with the
dismodule