diff options
Diffstat (limited to 'Lib/timeit.py')
-rw-r--r-- | Lib/timeit.py | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/Lib/timeit.py b/Lib/timeit.py index c3f6753c66..1ae59e0ccc 100644 --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 """Tool for measuring execution time of small code snippets. @@ -127,7 +127,7 @@ class Timer: if isinstance(setup, str): setup = reindent(setup, 4) src = template % {'stmt': stmt, 'setup': setup} - elif hasattr(setup, '__call__'): + elif callable(setup): src = template % {'stmt': stmt, 'setup': '_setup()'} ns['_setup'] = setup else: @@ -136,13 +136,13 @@ class Timer: code = compile(src, dummy_src_name, "exec") exec(code, globals(), ns) self.inner = ns["inner"] - elif hasattr(stmt, '__call__'): + elif callable(stmt): self.src = None if isinstance(setup, str): _setup = setup def setup(): exec(_setup, globals(), ns) - elif not hasattr(setup, '__call__'): + elif not callable(setup): raise ValueError("setup is neither a string nor callable") self.inner = _template_func(setup, stmt) else: @@ -191,9 +191,11 @@ class Timer: it = [None] * number gcold = gc.isenabled() gc.disable() - timing = self.inner(it, self.timer) - if gcold: - gc.enable() + try: + timing = self.inner(it, self.timer) + finally: + if gcold: + gc.enable() return timing def repeat(self, repeat=default_repeat, number=default_number): @@ -232,10 +234,10 @@ def repeat(stmt="pass", setup="pass", timer=default_timer, """Convenience function to create Timer object and call repeat method.""" return Timer(stmt, setup, timer).repeat(repeat, number) -def main(args=None): +def main(args=None, *, _wrap_timer=None): """Main program, used when run as a script. - The optional argument specifies the command line to be parsed, + The optional 'args' argument specifies the command line to be parsed, defaulting to sys.argv[1:]. The return value is an exit code to be passed to sys.exit(); it @@ -244,6 +246,10 @@ def main(args=None): When an exception happens during timing, a traceback is printed to stderr and the return value is 1. Exceptions at other times (including the template compilation) are not caught. + + '_wrap_timer' is an internal interface used for unit testing. If it + is not None, it must be a callable that accepts a timer function + and returns another timer function (used for unit testing). """ if args is None: args = sys.argv[1:] @@ -289,6 +295,8 @@ def main(args=None): # directory) import os sys.path.insert(0, os.curdir) + if _wrap_timer is not None: + timer = _wrap_timer(timer) t = Timer(stmt, setup, timer) if number == 0: # determine number so that 0.2 <= total time < 2.0 |