3

Is there a way to specify a teardown for the timeit.timeit() function in python? I know there are arguments for 'Statement' and 'Setup', but I haven't found a good way to perform a teardown.

Including the teardown code in my 'Statment' is skewing my timing for the code snippet I am trying to time. I require a teardown in order to release the hardware resources so that i can use the repeat function from the timeit module.

Harsh
  • 31
  • 3

1 Answers1

1

Nope, there's no really good way to do this. Looking at the source, you'll likely need to subclass the Timer class replacing their self.inner with a new version.

e.g.:

import inspect
import timeit

class MyTimer(timeit.Timer):
    def __init__(self, stmt="pass", setup="pass", teardown=None, timer=timeit.default_timer):
        timeit.Timer.__init__(self, stmt, setup, timer)
        # Pull the actual function to time off the original `self.inner` function.
        time_func = inspect.getargspec(self.inner).defaults[0]
        # It gets added as a keyword so that lookup in the 
        # current namespace is really fast.
        def _func(_it, _timer, _func=time_func):
            setup()
            total = 0.0
            for _i in _it:
                _t0 = _timer()
                _func()
                _t1 = timer()
                total += _t1 - _t0
                if teardown:
                    teardown()
            return total
        self.inner = _func

Beware though that you won't get as good of a timing this way since you're limited to timing a single test at a time. Unfortunately, I'm not clever enough to figure out a way to time multiple tests at a time with a teardown function that needs to be called for each one.

Alternatively, you could monkey patch the _template_func, basically just copying my _func from above before you create your timer. If you wanted to do this as cleanly as possible, maybe using mock to do the patching/unpatching would be a good idea (although you could also do it yourself without much trouble).

Note, we've played around with internal stuff here -- This answer could break at any time without warning, and it may only work on CPython since none of this is documented.

mgilson
  • 300,191
  • 65
  • 633
  • 696