Skip to content

profile

The Python profile module is a pure Python deterministic profiler that measures how often and how long each part of a program runs. It exposes the same interface as cProfile and produces profiling data that can be formatted into reports through the pstats module:

Language: Python
>>> import profile

>>> profile.run("sum(i * i for i in range(1000))")
         1006 function calls in 0.032 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.002    0.002    0.004    0.004 :0(sum)
     1001    0.002    0.000    0.002    0.000 <string>:1(<genexpr>)
        1    0.000    0.000    0.004    0.004 <string>:1(<module>)

Each row of the report describes one function in the profiled code:

  • ncalls: number of calls to that function
  • tottime: total time spent inside the function, excluding sub-calls
  • percall: time per call based on tottime
  • cumtime: cumulative time including everything the function called
  • percall: time per call based on cumtime
  • filename:lineno(function): location of the profiled code

Because profile is written in Python, it adds more overhead than its C counterpart cProfile, which is usually preferred for long-running programs. The profile module remains useful when you need a profiler that is easy to read, extend, or subclass in pure Python.

Key Features

  • Records every function call, return, and exception during program execution
  • Collects call counts, total time, and cumulative time per function
  • Profiles an expression, a callable, or an entire script or module
  • Writes results to a file that pstats can later load and sort
  • Supports a custom timer function for specialized measurements
  • Provides a calibration hook to subtract profiler overhead from timings

Frequently Used Classes and Functions

Object Type Description
profile.run() Function Profiles an expression string and prints or saves the results
profile.runctx() Function Profiles an expression with explicit globals and locals
profile.Profile Class Represents a single profiling session that can be driven directly
profile.Profile.runcall() Method Profiles a single callable with given arguments
profile.Profile.dump_stats() Method Saves collected statistics to a binary file for later analysis
pstats.Stats Class Loads profiling data and formats it into sortable reports

Examples

Profiling a small expression and printing the report:

Language: Python
>>> import profile

>>> profile.run("[i ** 2 for i in range(100)]")
         4 function calls in 0.000 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 <string>:1(<listcomp>)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)

Profiling a callable directly with the Profile.runcall() method:

Language: Python
>>> import profile

>>> def work(n):
...     return sum(i * i for i in range(n))
...
>>> pr = profile.Profile()
>>> pr.runcall(work, 1000)
332833500
>>> pr.print_stats()
         1005 function calls in 0.005 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.003    0.003 <stdin>:1(work)
     1001    0.001    0.000    0.001    0.000 <stdin>:2(<genexpr>)
        1    0.001    0.001    0.003    0.003 :0(sum)

Saving results to a file and inspecting them with pstats:

Language: Python
>>> import profile, pstats

>>> profile.run("sum(range(100_000))", "out.prof")
>>> stats = pstats.Stats("out.prof")
>>> stats.strip_dirs().sort_stats("cumulative").print_stats(5)
Tue May 19 15:42:16 2026    out.prof

         5 function calls in 0.002 seconds

   Ordered by: cumulative time
   List reduced from 6 to 5 due to restriction <5>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.002    0.002 profile:0(sum(range(100_000)))
        1    0.000    0.000    0.002    0.002 :0(exec)
        1    0.000    0.000    0.002    0.002 <string>:1(<module>)
        1    0.002    0.002    0.002    0.002 :0(sum)
        1    0.000    0.000    0.000    0.000 :0(setprofile)

Profiling a whole script from the command line:

Language: Shell
$ python -m profile -o out.prof myscript.py

Common Use Cases

The most common tasks for profile include:

  • Finding slow functions in a script or module
  • Capturing profiling data for later analysis with pstats
  • Subclassing the profiler to collect custom metrics
  • Measuring execution time with a non-default timer function
  • Comparing the cost of alternative implementations of a routine

Real-World Example

Consider a function that computes prime numbers using a naive algorithm. You can wrap the call in a Profile instance, dump the results to a file, and use pstats to print the five most expensive functions sorted by cumulative time:

Language: Python Filename: profile_primes.py
import profile
import pstats

def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

def count_primes(limit):
    return sum(1 for n in range(limit) if is_prime(n))

pr = profile.Profile()
pr.runcall(count_primes, 20_000)
pr.dump_stats("primes.prof")

stats = pstats.Stats("primes.prof")
stats.strip_dirs().sort_stats("cumulative").print_stats(5)

Running the script prints a table that shows how much time was spent inside count_primes() and is_prime(), which helps locate the bottleneck before refactoring or switching to a faster algorithm.

Tutorial

Profiling in Python: How to Find Performance Bottlenecks

In this tutorial, you'll learn how to profile your Python programs using numerous tools available in the standard library, third-party libraries, as well as a powerful tool foreign to Python. Along the way, you'll learn what profiling is and cover a few related concepts.

intermediate tools

For additional information on related topics, take a look at the following resources:


By Leodanis Pozo Ramos • Updated May 19, 2026