5 Best Ways to Create a Python Program for a Lap Timer

Rate this post

πŸ’‘ Problem Formulation: In the world of sports, timing is crucial. A lap timer is an essential tool used to measure intervals or ‘laps’ during a race or session of exercise. The task involves creating a Python program that starts timing at the press of a button, records the time for a lap when prompted, and displays each lap time until the timer is stopped. The desired output is a list of lap times with the total time elapsed.

Method 1: Using Time Module and Keyboard Input

An effective way to build a lap timer is to use the time module in Python to keep track of the current time and calculate differences between laps. This method requires monitoring keyboard input to start, lap, and stop the timer.

Here’s an example:

import time

print("Press ENTER to start the timer, press Ctrl+C to stop.")
input()  
startTime = time.time()
lastTime = startTime
lapNum = 1

try:
    while True:
        input()
        lapTime = round(time.time() - lastTime, 2)
        totalTime = round(time.time() - startTime, 2)
        print(f"Lap #{lapNum}: {lapTime} (Total: {totalTime})")
        lapNum += 1
        lastTime = time.time()
except KeyboardInterrupt:
    print("\nDone.")

The output of this code will display lap times upon each ENTER key press, and total time elapsed until the program is interrupted with Ctrl+C:

Lap #1: 3.45 (Total: 3.45)
Lap #2: 2.61 (Total: 6.06)
....
Done.

This Python script initializes the timer when the ENTER key is first pressed. Each subsequent ENTER key press records a new lap, printing the time taken for that lap along with the total time since the timer started. The try...except KeyboardInterrupt is used to handle the Ctrl+C command, which stops the timer.

Method 2: Using tkinter for a GUI-based Timer

\

When we want to create a more user-friendly lap timer, we can use Python’s tkinter library to create a graphical user interface (GUI). This allows users to interact with buttons instead of key presses in the console.

Here’s an example:

import tkinter as tk
import time

def start_timer():
    global startTime, running
    startTime = time.time()
    running = True
    update_timer()

def lap():
    if running:
        lap_time = time.time() - startTime
        listbox.insert(tk.END, f"Lap {listbox.size() + 1}: {round(lap_time, 2)} seconds")

def update_timer():
    if running:
        elapsed_time = time.time() - startTime
        timer_label.config(text=f'{round(elapsed_time, 2)}')
        window.after(10, update_timer)

def stop_timer():
    global running
    running = False

window = tk.Tk()
window.title("Lap Timer")

startTime = 0
running = False

timer_label = tk.Label(window, text='0.00', font=('Helvetica', 24))
timer_label.pack()

listbox = tk.Listbox(window)
listbox.pack()

start_button = tk.Button(window, text='Start', command=start_timer)
start_button.pack()

lap_button = tk.Button(window, text='Lap', command=lap)
lap_button.pack()

stop_button = tk.Button(window, text='Stop', command=stop_timer)
stop_button.pack()

window.mainloop()

The output of this code snippet is a window with a timer label displaying the elapsed time, and buttons to start the timer, record laps, and stop the timer. Laps are listed in a box with their times.

The code snippet defines the main window using tkinter and adds a label and buttons for controlling the timer. The update_timer function is recursively called to refresh the timer label every 10 milliseconds if the timer is running. When the user clicks on “Lap”, the current time is recorded in a listbox.

Method 3: Using Thread for a Concurrent Lap Timer

Threading in Python can be employed to create a lap timer that runs concurrently with other parts of a program. This is useful when the timing functionality should work in the background, allowing other processes to execute simultaneously.

Here’s an example:

import time
import threading

class LapTimer(threading.Thread):
    def __init__(self):
        super().__init__()
        self.startTime = None
        self.laps = []
        self.running = False
        
    def run(self):
        self.running = True
        self.startTime = time.time()
        while self.running:
            time.sleep(0.1)
    
    def lap(self):
        if self.startTime:
            self.laps.append(time.time() - self.startTime)
            print(f'Lap {len(self.laps)}: {self.laps[-1]}')

    def stop(self):
        self.running = False
        self.endTime = time.time()
        self.totalTime = self.endTime - self.startTime
        print(f'Total Time: {self.totalTime}')
        print('Laps:', self.laps)

timer = LapTimer()
timer.start()
time.sleep(1)  # Simulating waiting time
timer.lap()
time.sleep(2)  # Simulating waiting time
timer.lap()
timer.stop()

The output of this code after running will be:

Lap 1: 1.0
Lap 2: 3.0
Total Time: 3.1
Laps: [1.0, 3.0]

In this method, a class LapTimer is created that extends threading.Thread, which allows the timer to run in a separate thread. The run method keeps the timer going and listening for laps and stop signals. The lap and stop methods can be called to record a lap time and stop the timer, respectively, providing output each time.

Method 4: Using a High-Resolution Timer with time.perf_counter()

For more precise timing requirements, Python offers the time.perf_counter() function, which provides a high-resolution timer. This method is especially useful in situations requiring greater time accuracy.

Here’s an example:

import time

lap_times = []
try:
    input("Press Enter to start timer...")
    start_time = time.perf_counter()
    while True:
        input("Press Enter to lap...")
        lap_end = time.perf_counter()
        lap_times.append(lap_end - start_time)
        start_time = lap_end
        print(f"New Lap: {lap_times[-1]:.4f}s")
except KeyboardInterrupt:
    print("Timer stopped.")
    print(f"Total Laps: {len(lap_times)}")
    for i, lap_time in enumerate(lap_times, start=1):
        print(f"Lap {i}: {lap_time:.4f}s")

The output of this code will be a series of lap times recorded with high precision each time the Enter key is pressed:

New Lap: 2.3456s
New Lap: 1.7890s
...
Timer stopped.
Total Laps: 2
Lap 1: 2.3456s
Lap 2: 1.7890s

This code uses time.perf_counter() to capture the more precise time for the start of the timer and each lap. The difference between the current and previous lap time is calculated to get individual lap times with high precision. The Ctrl+C interrupt stops the timer and prints out the lap details.

Bonus One-Liner Method 5: Using the timeit Module

Although not typically used for lap timing, Python’s timeit module can be manipulated to serve as an impromptu lap timer in a pinch. This one-liner is more of a demonstration of Python’s flexibility than a practical method.

Here’s an example:

import timeit 

laps = [{i: timeit.timeit(stmt='pass', number=1)} for i in range(10)]
print(laps)

The output consists of a list of dictionaries with a counter as the key and the elapsed time to execute a ‘pass’ statement as the value:

[{0: 1.9073486328125e-06}, ..., {9: 1.9073486328125e-06}]

This code uses a list comprehension together with the timeit.timeit() function to simulate a series of 10 ‘laps’, each of which is a pass statement executed once. It’s an interesting use of timeit to mock-up timer functionality, but not recommended for actual lap timing due to the overhead of the timeit function itself.

Summary/Discussion

  • Method 1: The Time Module and Keyboard Input. Strengths: Simple implementation with no additional libraries needed. Weaknesses: Console-based and requires precise user input.
  • Method 2: tkinter for a GUI-based Timer. Strengths: User-friendly GUI. Weaknesses: Requires basic knowledge of GUI programming and a running event loop.
  • Method 3: Using Thread for Concurrent Timing. Strengths: Allows timer to run in the background, enabling multitasking. Weaknesses: May introduce complexity due to thread management.
  • Method 4: High-Resolution Timer with time.perf_counter(). Strengths: Provides high accuracy timer. Weaknesses: Requires more precision with the stop/start timing to be effective.
  • Method 5: Using the timeit Module. Strengths: Quick and concise one-liner. Weaknesses: Inefficient and not practical for actual lap timing.