Skip to content

Instantly share code, notes, and snippets.

@sumeet
Created August 3, 2011 21:48
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save sumeet/1123871 to your computer and use it in GitHub Desktop.
Save sumeet/1123871 to your computer and use it in GitHub Desktop.
A Python timer class.
import time
class Stopwatch(object):
"""A stopwatch utility for timing execution that can be used as a regular
object or as a context manager.
NOTE: This should not be used an accurate benchmark of Python code, but a
way to check how much time has elapsed between actions. And this does not
account for changes or blips in the system clock.
Instance attributes:
start_time -- timestamp when the timer started
stop_time -- timestamp when the timer stopped
As a regular object:
>>> stopwatch = Stopwatch()
>>> stopwatch.start()
>>> time.sleep(1)
>>> 1 <= stopwatch.time_elapsed <= 2
True
>>> time.sleep(1)
>>> stopwatch.stop()
>>> 2 <= stopwatch.total_run_time
True
As a context manager:
>>> with Stopwatch() as stopwatch:
... time.sleep(1)
... print repr(1 <= stopwatch.time_elapsed <= 2)
... time.sleep(1)
True
>>> 2 <= stopwatch.total_run_time
True
"""
def __init__(self):
"""Initialize a new `Stopwatch`, but do not start timing."""
self.start_time = None
self.stop_time = None
def start(self):
"""Start timing."""
self.start_time = time.time()
def stop(self):
"""Stop timing."""
self.stop_time = time.time()
@property
def time_elapsed(self):
"""Return the number of seconds that have elapsed since this
`Stopwatch` started timing.
This is used for checking how much time has elapsed while the timer is
still running.
"""
assert not self.stop_time, \
"Can't check `time_elapsed` on an ended `Stopwatch`."
return time.time() - self.start_time
@property
def total_run_time(self):
"""Return the number of seconds that elapsed from when this `Stopwatch`
started to when it ended.
"""
return self.stop_time - self.start_time
def __enter__(self):
"""Start timing and return this `Stopwatch` instance."""
self.start()
return self
def __exit__(self, type, value, traceback):
"""Stop timing.
If there was an exception inside the `with` block, re-raise it.
>>> with Stopwatch() as stopwatch:
... raise Exception
Traceback (most recent call last):
...
Exception
"""
self.stop()
if type:
raise type, value, traceback
import time
import unittest
import stopwatch
class MockSystemClock(object):
"""Represents a system clock with time starting at `0` and incremented
whenever `sleep()` is called.
Meant to replace the `time()` and `sleep()` functions in the `time` module.
>>> clock = MockSystemClock()
>>> clock.time()
0
>>> clock.sleep(1)
>>> clock.time()
1
"""
def __init__(self):
"""Initialize the current system time to `0`."""
self._system_time = 0
def time(self):
"""Return the current system time."""
return self._system_time
def sleep(self, seconds):
"""Increment the system time by `seconds`."""
self._system_time += seconds
class StopwatchTestCase(unittest.TestCase):
def setUp(self):
"""Monkey patch `time.time()` and `time.sleep()` to point to the
corresponding methods on a new `MockSystemClock` instance.
"""
self._time_time = time.time
self._time_sleep = time.sleep
mock_system_clock = MockSystemClock()
time.time = mock_system_clock.time
time.sleep = mock_system_clock.sleep
def tearDown(self):
"""Restore the `time` module."""
time.time = self._time_time
time.sleep = self._time_sleep
def test_stopwatch_as_object(self):
"""Test using a `Stopwatch` as a regular object."""
sw = stopwatch.Stopwatch()
sw.start()
self.assertEqual(0, sw.time_elapsed)
time.sleep(1)
self.assertEqual(1, sw.time_elapsed)
sw.stop()
self.assertEqual(1, sw.total_run_time)
def test_stopwatch_as_context_manager(self):
"""Test using a `Stopwatch` as a context manager."""
with stopwatch.Stopwatch() as sw:
sw.start()
self.assertEqual(0, sw.time_elapsed)
time.sleep(1)
self.assertEqual(1, sw.time_elapsed)
self.assertEqual(1, sw.total_run_time)
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment