Preshing on ProgrammingPreshing on Programming

Timing Your Code Using Python's "with" Statement

It’s common to want to time a piece of code. In Python, the with statement provides a convenient way to do so.

If you’ve followed my previous post, The Python with Statement by Example, you should have no problem following along here. All you need is a class which implements the __enter__ and __exit__ methods:

import time

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self

    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

Of course, this is not a revolutionary idea. We’re just subtracting a couple of time.clock calls. If you google around, you’ll find several people suggesting to use the with statement in the same way. I’ve only tweaked the implementation details.

In the above class, the __enter__ method returns the Timer object itself, allowing us to assign it to a local variable using the "as" target part of the with statement. So we can write the following:

import httplib

with Timer() as t:
    conn = httplib.HTTPConnection('google.com')
    conn.request('GET', '/')

print('Request took %.03f sec.' % t.interval)

The main advantage of using the with statement is that the __exit__ method will be called regardless of how the nested block exits. Even if an exception is raised in the middle of the nested block – as would happen if network problems interfere with the above HTTPConnection – the __exit__ method will be called. To see the result, though, we’d have to handle the exception in a try/finally block:

try:
    with Timer() as t:
        conn = httplib.HTTPConnection('google.com')
        conn.request('GET', '/')
finally:
    print('Request took %.03f sec.' % t.interval)

Now, even if your network cable comes unplugged, you’ll still see the running time of this code.

Of course, Python has its own set of debugging and profiling modules in the standard library. Use whatever suits your purpose.