Question

How to Measure Python Program Execution Time

pythontimeexecution-time

Question

I have a Python command-line program that takes a while to finish, and I want to measure exactly how long it takes to run from start to finish.

I looked at Python's timeit module, but it seems more suited to benchmarking small code snippets. How can I measure the execution time of the entire program?

Short Answer

By the end of this page, you will understand how to measure the runtime of a complete Python program, when to use time.time() versus time.perf_counter(), how to print elapsed time cleanly, and what mistakes to avoid when timing real programs.

Concept

In Python, measuring a program's execution time usually means recording a start time, running the code, recording an end time, and subtracting the two.

For timing a full program, the most common tool is the built-in time module.

The key idea is:

elapsed = end - start

This matters because developers often need to:

  • check whether a script is too slow
  • compare two implementations
  • monitor long-running tasks
  • log performance in production tools

For full-program timing, timeit is usually not the first choice. timeit is excellent for benchmarking small isolated snippets many times under controlled conditions. But when you want to measure an entire script or command-line process, using time.perf_counter() or time.time() directly is simpler and more appropriate.

In modern Python, time.perf_counter() is usually the best choice for measuring elapsed time because it provides a high-resolution timer intended for duration measurement.

Mental Model

Think of timing a program like using a stopwatch:

  • press start right before the work begins
  • press stop right after the work ends
  • read the difference

In code:

  • start = ... is pressing start
  • your program does its work
  • end = ... is pressing stop
  • end - start is the elapsed duration

If you want the total runtime of the program, place the stopwatch around the whole main part of the script.

Take Quiz

Syntax and Examples

The basic syntax uses Python's time module.

Recommended: time.perf_counter()

import time

start = time.perf_counter()

# Code you want to time
for i in range(3):
    time.sleep(1)

end = time.perf_counter()

print(f"Execution time: {end - start:.4f} seconds")

Why this works

  • time.perf_counter() gives a precise timer for measuring elapsed time.
  • The subtraction gives the total duration.
  • :.4f formats the result to 4 decimal places.

Timing an entire program

import time

start = time.perf_counter()

print("Program starting...")

# Simulate work
for i in range(5):
    print(f"Step {i + 1}")
    time.sleep(0.5)

print("Program finished.")

end = time.perf_counter()
print(f"Total runtime: {end - start:.2f} seconds")

Alternative: time.time()

import time

start = time.time()

# Code here
time.sleep(2)

end = time.time()
print(f"Elapsed: {end - start:.2f} seconds")

This also works, but perf_counter() is generally better for measuring durations.

Step by Step Execution

Consider this example:

import time

start = time.perf_counter()

print("Working...")
time.sleep(2)

end = time.perf_counter()
print(end - start)

Here is what happens step by step:

  1. import time

    • Python loads the time module.
  2. start = time.perf_counter()

    • Python stores the current high-resolution timer value in start.
    • This is the moment timing begins.
  3. print("Working...")

    • The message is printed.
    • Printing takes a tiny amount of time and is included in the measurement.
  4. time.sleep(2)

    • The program pauses for about 2 seconds.
    • This time is included in the total runtime.
  5. end = time.perf_counter()

    • Python stores the timer value again after the work is done.
  6. print(end - start)

    • Python subtracts the start value from the end value.
    • The result is approximately 2.0 seconds, plus a tiny bit more for printing and other overhead.

This pattern works the same way for larger scripts: start the timer before the main work and stop it after the main work finishes.

Real World Use Cases

Measuring full-program execution time is useful in many practical situations:

  • Data processing scripts

    • Measure how long it takes to parse CSV files, transform rows, and write output.
  • Command-line tools

    • Track runtime for backup scripts, file converters, and deployment helpers.
  • API clients

    • Measure the total time spent making requests and processing responses.
  • Batch jobs

    • Time nightly jobs such as report generation or database synchronization.
  • Machine learning scripts

    • Measure training, preprocessing, or evaluation durations.
  • Automation tasks

    • Check how long web scraping, browser automation, or scheduled jobs take.

Example:

import time

start = time.perf_counter()

# Load data
# Clean data
# Save results

end = time.perf_counter()
print(f"Job completed in {end - start:.2f} seconds")
Take Quiz

Real Codebase Usage

In real projects, developers usually do more than just print a raw number.

Common patterns

1. Timing the main entry point

import time


def main():
    # program logic here
    time.sleep(1)


if __name__ == "__main__":
    start = time.perf_counter()
    main()
    end = time.perf_counter()
    print(f"Runtime: {end - start:.3f} seconds")

This keeps timing code separate from business logic.

2. Logging instead of printing

import time
import logging

logging.basicConfig(level=logging.INFO)

start = time.perf_counter()

# program work
time.sleep(1)

elapsed = time.perf_counter() - start
logging.info("Program finished in %.3f seconds", elapsed)

This is common in production scripts.

3. Timing even when errors happen

import time

start = time.perf_counter()

try:
    # main work
    time.sleep(1)
finally:
    elapsed = time.perf_counter() - start
    print(f"Elapsed time: {elapsed:.3f} seconds")

Using finally ensures the time is reported even if an exception occurs.

4. Timing specific stages

import time

start = time.perf_counter()

# stage 1
time.sleep(0.5)
stage1_end = time.perf_counter()

# stage 2
time.sleep(0.8)
end = time.perf_counter()

print(f"Stage 1: {stage1_end - start:.3f}s")
print(f"Stage 2: {end - stage1_end:.3f}s")
print(f"Total: {end - start:.3f}s")

This helps identify slow parts of a program.

Common Mistakes

Here are common beginner mistakes when measuring execution time.

1. Using timeit for a full script

timeit is great for micro-benchmarks, but it is not the simplest tool for timing an entire command-line program.

Use this instead:

import time

start = time.perf_counter()
# full program logic
end = time.perf_counter()

2. Starting the timer too late

Broken example:

import time

time.sleep(2)
start = time.perf_counter()

This misses some of the runtime.

Fix: place the timer before the code you want to measure.

3. Stopping the timer too early

Broken example:

import time

start = time.perf_counter()
time.sleep(1)
end = time.perf_counter()
print("Saving results...")

If saving results matters, it should be included before recording end.

4. Using the wrong timer for durations

time.time() works, but time.perf_counter() is usually better for elapsed time measurement.

5. Forgetting that setup and output take time

If your timer includes file loading, printing, network calls, or sleeping, those all affect the result. That is not wrong—but you should be clear about what exactly you are measuring.

6. Ignoring exceptions

If the program crashes before reaching the end time, you may get no timing output.

Use try/finally when needed:

import time

start = time.perf_counter()
try:
    # work
    pass
finally:
    print(time.perf_counter() - start)

Comparisons

ToolBest forGood choice for full program timing?Notes
time.perf_counter()Measuring elapsed duration accuratelyYesBest general choice for timing runtime
time.time()Getting wall-clock timeYesSimpler, but less ideal for precise duration measurement
timeitBenchmarking small snippets repeatedlyNoUseful for comparing tiny pieces of code

time.perf_counter() vs time.time()

Featuretime.perf_counter()time.time()
Designed for elapsed timingYesNot specifically
High resolutionYesUsually lower
Affected by wall-clock meaningNo practical need hereRepresents actual system time
Best for measuring runtimeYesAcceptable

Full-program timing vs micro-benchmarking

  • Full-program timing measures the total runtime of a script.
  • Micro-benchmarking measures a small code fragment very carefully, often many times.

If your question is "How long does my script take to finish?" use time.perf_counter().

Take Quiz

Cheat Sheet

import time

start = time.perf_counter()
# code to measure
end = time.perf_counter()

elapsed = end - start
print(f"Elapsed: {elapsed:.4f} seconds")

Quick rules

  • Use time.perf_counter() for elapsed time measurement.
  • Put start immediately before the code you want to measure.
  • Put end immediately after the code you want to measure.
  • Subtract: end - start.
  • Format output with f-strings if needed.

Common pattern

import time


def main():
    # program logic
    pass


if __name__ == "__main__":
    start = time.perf_counter()
    main()
    elapsed = time.perf_counter() - start
    print(f"Runtime: {elapsed:.3f} seconds")

Timing with error safety

import time

start = time.perf_counter()
try:
    # work
    pass
finally:
    print(f"Elapsed: {time.perf_counter() - start:.3f} seconds")

Avoid

  • using timeit for whole-program timing when simple elapsed timing is enough
  • starting the timer after setup has already happened
  • stopping the timer before cleanup or saving finishes

FAQ

Should I use timeit to measure a full Python script?

Usually no. timeit is mainly for benchmarking small snippets. For a whole script, time.perf_counter() is simpler and more appropriate.

What is the best way to measure how long a Python program takes?

Use time.perf_counter() before and after the main work, then subtract the two values.

Is time.time() good enough?

Yes, it often works fine, especially for simple scripts. But time.perf_counter() is generally the better choice for measuring elapsed durations.

Why is my measured time slightly more than sleep(2)?

Because printing, function calls, and interpreter overhead also take a small amount of time.

How do I time a script even if it crashes?

Wrap the program logic in try/finally and print the elapsed time in the finally block.

Can I measure only part of my program instead of the whole thing?

Yes. Put the start and end timer calls around only that section.

How do I print execution time nicely?

Use formatting such as:

print(f"Elapsed: {elapsed:.3f} seconds")
Take Quiz

Mini Project

Description

Build a small command-line Python script that simulates a long-running task and reports how long the entire program took to complete. This demonstrates how to measure full-program execution time in a practical way.

Goal

Create a script that runs several steps, waits briefly in each step, and prints the total runtime at the end.

Requirements

  1. Import Python's time module.
  2. Record a start time before the main work begins.
  3. Simulate at least three steps of work.
  4. Record the end time after all work is finished.
  5. Print the total elapsed time in seconds.
Take Quiz

Keep learning

Related questions

View more