How do you profile Python code with cProfile?
Profiling is the process of measuring where a program spends its time, so you can direct optimization efforts at the actual bottleneck rather than guessing. Python's built-in `cProfile` module is a deterministic profiler that instruments every function call and records call counts, total time, and cumulative time per function.
The simplest usage is from the command line: `python -m cProfile -s cumulative my_script.py`. The `-s cumulative` flag sorts output by cumulative time — time spent in a function *including* all callees. This is usually the most useful sort for finding the root of slowness. Other sort keys: `tottime` (time in the function excluding callees — useful for finding tight CPU loops), `ncalls` (call frequency), `filename`.
From within code, you wrap the target section: ```python import cProfile with cProfile.Profile() as pr: result = expensive_function() pr.print_stats(sort='cumulative') ```
For programmatic analysis, dump to a file and load with `pstats`: ```python pr.dump_stats('output.prof') import pstats stats = pstats.Stats('output.prof') stats.strip_dirs().sort_stats('cumulative').print_stats(20) ``` `strip_dirs()` removes path prefixes for cleaner output; `print_stats(20)` shows only the top 20 functions.
For visualization, **snakeviz** (`pip install snakeviz; snakeviz output.prof`) renders an interactive sunburst chart of the call tree in a browser — far easier to navigate than raw text for large profiles. **gprof2dot** generates call-graph DOT files.
cProfile has overhead because it instruments *every* function call — typically 10-50x slowdown. For production profiling of a live service, **py-spy** is a sampling profiler that attaches to a running process without modification or restart, reads the Python stack via ptrace, and produces flamegraphs with minimal overhead.
Profile the *same workload* you are optimizing — synthetic microbenchmarks often mislead. Use `timeit` for isolated micro-benchmarks of specific expressions. For memory profiling (not CPU), use `memory_profiler` or `tracemalloc` (built-in since Python 3.4).
Knows how to run cProfile from command line and sort by cumulative time. Can interpret the output columns. May not know pstats, snakeviz, or the distinction between tottime and cumtime.
Explains cumtime vs. tottime semantics, demonstrates programmatic usage with pstats, mentions snakeviz or flamegraph visualization, distinguishes cProfile (deterministic) from py-spy (sampling), and knows when to use tracemalloc for memory profiling.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment