Getting Started

This page will walk you through how to get started with the Stopwatch Kit.

Guide

When we try to calculate the runtime of a program, we usually use the default_timer function defined in the timeit module.

current_timer_count: float = float(timeit.default_timer())
time.sleep(3)
print(float(timeit.default_timer()) - current_timer_count)

However, in some projects, we may need to count the running time of each phase and manage and maintain it. At this point, the calculations demonstrated in the sample code above will be very inconvenient. When there are too many phase nodes that need to be calculated, a lot of duplicate code will be generated, resulting in code redundancy and unfavorable maintenance.

For Python introductors, the calculations demonstrated in the sample code above may not be good for understanding.

In the following, we show you how to use Stopwatch to calculate the running time of a program through several consecutive pieces of Python code.

Import module

For the sake of understanding, we need to use the sleep function in the time module to simulate the running process of the program.

import time

Before using Stopwatch, we should import Stopwatch:

from stopwatch import Stopwatch

If you need to catch a related exception for Stopwatch, you should import:

from stopwatch import StatusError
from stopwatch import LapNameError

Create Stopwatch

The functionality of Stopwatch is defined in a class called Stopwatch. Therefore, we can create one or more Stopwatch instances by instantiating the Stopwatch class.

demo_stopwatch: Stopwatch = Stopwatch(
default_precision = None
)

The constructor method of class Stopwatch contains an optional parameter default_precision of data type int that indicates the timer precision (number of decimal places) of the Stopwatch instance being created. If the parameter is not supplied or the value is None, the default value for this parameter is 3.

Start Stopwatch

In the above, we defined a variable called demo_stopwatch, which is a Stopwatch instance. Now let's try to make the demo_stopwatch start timing.

demo_stopwatch.start()

Next, we use the time.sleep function to suspend the current thread for 3 seconds, simulating the first phase of the program code to run.

time.sleep(3)

Record Stopwatch

When there are multiple program phases in our project, phased timing is essential in order to calculate the runtime of each phase. In the sample code above we used the time.sleep function to simulate the first phase of the program run, then we used the lap method to record the timing results.

lap_of_watch: float = demo_stopwatch.lap(
lap_name = 'stage1'
)

There are 2 types of timing records:

  • Named timing record

  • Anonymous timing record

The method lap has an optional parameter lap_name of data type str, which indicates the unique name of the timed record. If this parameter is not supplied or the value is None, the timing record is anonymous.

This method returns a return value of data type float indicating the timing result of the current phase. If this is the first timing record, the timing is the time from the Stopwatch to the current interval (in seconds); otherwise, the timing is from the last timing record to the current interval (in seconds).

Note that the name of the timed record must be unique within the current Stopwatch instance, ie it cannot be repeated. Otherwise, a LapNameError exception will be thrown.

Next, we use the time.sleep function again to suspend the current thread for 1 second, simulating the second phase of the program code to run.

time.sleep(1)

Then, record the timing results of the second phase.

lap_of_watch: float = demo_stopwatch.lap(
lap_name = 'stage2'
)

Stop Stopwatch

In the above, we used the time.sleep function to simulate the first and second phases of the program run, and used the lap method to record the timing of the first and second phases of the program.

Now let's stop the demo_stopwatch.

total_of_watch: float = demo_stopwatch.stop()

Method stop returns a return value of data type float indicating the total time (in seconds) of the current Stopwatch instance from the first time it started to the time it was stopped.

The return value can be ignored, we can use the get_watch method to instantly check the total time of the Stopwatch instance:

total_of_watch: float = demo_stopwatch.get_watch(
watch_precision: int = None
)

The method get_watch has an optional parameter of data type int that indicates the total precision (decimal point) obtained. If the parameter is not supplied or the value is None, the default value for this parameter is the value of the Stopwatch class constructor method parameter default_precision.

Note that when using the get_watch method in a Stopwatch version earlier than 0.1.3, you should ensure that the Stopwatch instance has stopped timing, otherwise a StatusError exception will be raised.

We can check the status of the current Stopwatch instance using the get_status method.

if demo_stopwatch.get_status() == StopwatchStatus.Stopped:
print('stopwatch has stopped timing')

StopwatchStatus is a predefined Stopwatch state enumerator that can be compared to the return value of the method get_status .

from stopwatch import StopwatchStatus

Get Stopwatch record

In the above, we used the lap method to record the timing results of the first and second phases of the program in stages. Now we try to get these timing records.

Get named timing record

We can get the named timing record using the get_lap method.

lap_of_watch: float = demo_stopwatch.get_lap(
lap_name = 'stage1',
lap_precision = 3
)

The method get_lap has 2 parameters, which are:

Parameter

Type

Optional

Description

lap_name

str

False

The unique name of the timed record.

lap_precision

int

True

Get the timing record accuracy (number of decimal places).

The parameter lap_precision is optional. If the parameter is not supplied or the value is None, the default value for this parameter is the value of the Stopwatch class constructor method parameter default_precision.

Note that if the specified timing record name does not exist, a LapNameError exception will be thrown.

If we need to determine if a timing record exists, we can check it with the has_lap method.

if not demo_stopwatch.has_lap(
lap_name = 'stage1'
):
print('no such lap')

Get anonymous timing records

It's worth noting that anonymous timed records are not really anonymous, but instead use lap_ and record number combination to name the timed record (for example: lap_1). Therefore, we can also get the anonymous timing record using the get_lap method, but the more convenient way is to use the get_lap_by_number method.

lap_of_watch: float = demo_stopwatch.get_lap_by_number(
lap_number = 1,
lap_precision = 3
)

The difference from the method get_lap is that the method's parameter lap_number indicates the number of the anonymous record (starting at 1) and its data type is int. The get_lap method is still called inside the method to get the anonymous timing record.

Note that if you use this method to get a non-anonymous timing record, a LapNameError exception will be thrown.

To give you a clearer understanding of the relationship between named timing records and anonymous timing records, we will explain them in detail through the demo below.

demo_stopwatch.lap('stage1')
demo_stopwatch.lap()
demo_stopwatch.get_lap_by_number(1)

In the sample code above, we recorded 2 current Stopwatch current timing results, one for each of the timed record and the anonymous timed record. The contents of the Timed Recordset in the Stopwatch instance are now as follows:

[
'stage1',
'lap_2'
]

In the sample code above, an exception is thrown when the first named timing record is obtained using the get_lap_by_number method:

LapNameError(no such lap: lap_1)

Because there is no named timing record named lap_1 in the current record set of the Stopwatch instance, a LapNameError exception is inevitable. It can be seen that the anonymous timing record only names the record in the default form (a combination of lap_ and record number).

Get the average result of all timing records

If we need to get the average timing of all the timed records in the current Stopwatch instance, we can use the get_average_of_laps method.

average_of_laps: float = demo_stopwatch.get_average_of_laps(
average_precision = None
)

The method get_average_of_laps has an optional parameter average_precision of data type int, which indicates the precision (number of decimal places) of the average result of the acquired timed records. If the parameter is not supplied or the value is None, the method behaves the same as get_lap.

Enumerate all timing record names

We can also use the get_laps method to enumerate the unique names of all timed records, which also contain anonymous timed records.

for lap_name in demo_stopwatch.get_laps():
print(lap_name)

The method get_laps returns the return value of the data type list, which contains the unique names of all the timed records, and the member data type is str.

Get the number of timing records

We can use the get_lap_count method to get the total number of timed records for the current Stopwatch instance.

number_of_laps: int = demo_stopwatch.get_lap_count()

Reset Stopwatch

Each Stopwatch instance will generate status data for the current instance (for example: timing records, etc...) from the start of the count. If we need to clear this data, we should reset the Stopwatch instance to its initial state.

Tips: The Stopwatch instance can repeat the start and end, and the timed record and total time will be accumulated until it is reset.

demo_stopwatch.reset()

When the Stopwatch instance is reset, all state data is cleaned up and the Stopwatch instance is reset to its initial state.

Note that if the Stopwatch instance is still in a timed state, a StatusError exception will be raised. You can check the status of a Stopwatch instance using the get_status method.

Example

The following is a full Python sample code that demonstrates how to use Stopwatch.

Source code

quickstart.py
# quickstart.py is python-3.7.4 source file
import time
from stopwatch import Stopwatch
from stopwatch import StopwatchStatus
# define main function
def main():
# instantiate stopwatch
demo_stopwatch: Stopwatch = Stopwatch(
default_precision = 3 # ignorable
)
# make stopwatch start timing
demo_stopwatch.start()
# the first stage of the simulation program
time.sleep(3)
# it takes time to record the first phase of the program
demo_stopwatch.lap('stage1')
# the second stage of the simulation program
time.sleep(1)
# it takes time to record the second phase of the program
demo_stopwatch.lap('stage2')
# try checking the stopwatch total time every 1 second
for count in range(3):
print('{COUNT} check: {WATCH_SECONDS} seconds'.format(
COUNT = count + 1,
WATCH_SECONDS = demo_stopwatch.get_watch()
))
# record cycle check time spent on stopwatch
demo_stopwatch.lap('stage3')
# get the status of stopwatch
if demo_stopwatch.get_status() == StopwatchStatus.Started:
print('stopwatch is timing...')
# stop and print the timing of the stopwatch
print(
(
'total: {TOTAL_SECONDS} seconds\n'
'stage1: {STAGE1_SECONDS} seconds\n'
'stage2: {STAGE2_SECONDS} seconds\n'
'stage3: {STAGE3_SECONDS} seconds\n'
'----------\n'
'average of stages: {AVERAGE_SECONDS} seconds'
).format(
TOTAL_SECONDS = demo_stopwatch.stop(),
STAGE1_SECONDS = demo_stopwatch.get_lap('stage1'),
STAGE2_SECONDS = demo_stopwatch.get_lap('stage2'),
STAGE3_SECONDS = demo_stopwatch.get_lap('stage2'),
AVERAGE_SECONDS = demo_stopwatch.get_average_of_laps()
)
)
# reset stopwatch
demo_stopwatch.reset()
# define virtual main function
if __name__ == '__main__':
main()

Result

1 check: 4.001 seconds
2 check: 4.002 seconds
3 check: 4.003 seconds
stopwatch is timing...
total: 4.006 seconds
stage1: 3.0 seconds
stage2: 1.001 seconds
stage3: 1.001 seconds
----------
average of stages: 1.335 seconds