diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2014-08-23 03:13:50 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2014-08-23 03:13:50 (GMT) |
commit | ef3b9ed0ac99c3825ebf7b716d504d52d080f8c2 (patch) | |
tree | 4c0d152397ca91b243e3b00b92a0db3c44f62c09 /Lib | |
parent | 682c04c70c9af6df68cacce47c2f0d18c31dd443 (diff) | |
download | cpython-ef3b9ed0ac99c3825ebf7b716d504d52d080f8c2.zip cpython-ef3b9ed0ac99c3825ebf7b716d504d52d080f8c2.tar.gz cpython-ef3b9ed0ac99c3825ebf7b716d504d52d080f8c2.tar.bz2 |
Issue #2527: Add a *globals* argument to timeit functions, in order to override the globals namespace in which the timed code is executed.
Patch by Ben Roberts.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_timeit.py | 16 | ||||
-rwxr-xr-x | Lib/timeit.py | 30 |
2 files changed, 32 insertions, 14 deletions
diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py index 625fb8d..b3a96bb 100644 --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -86,9 +86,10 @@ class TestTimeit(unittest.TestCase): def fake_callable_stmt(self): self.fake_timer.inc() - def timeit(self, stmt, setup, number=None): + def timeit(self, stmt, setup, number=None, globals=None): self.fake_timer = FakeTimer() - t = timeit.Timer(stmt=stmt, setup=setup, timer=self.fake_timer) + t = timeit.Timer(stmt=stmt, setup=setup, timer=self.fake_timer, + globals=globals) kwargs = {} if number is None: number = DEFAULT_NUMBER @@ -127,6 +128,17 @@ class TestTimeit(unittest.TestCase): timer=FakeTimer()) self.assertEqual(delta_time, 0) + def test_timeit_globals_args(self): + global _global_timer + _global_timer = FakeTimer() + t = timeit.Timer(stmt='_global_timer.inc()', timer=_global_timer) + self.assertRaises(NameError, t.timeit, number=3) + timeit.timeit(stmt='_global_timer.inc()', timer=_global_timer, + globals=globals(), number=3) + local_timer = FakeTimer() + timeit.timeit(stmt='local_timer.inc()', timer=local_timer, + globals=locals(), number=3) + def repeat(self, stmt, setup, repeat=None, number=None): self.fake_timer = FakeTimer() t = timeit.Timer(stmt=stmt, setup=setup, timer=self.fake_timer) diff --git a/Lib/timeit.py b/Lib/timeit.py index ead2030..5971d37 100755 --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -60,6 +60,8 @@ default_number = 1000000 default_repeat = 3 default_timer = time.perf_counter +_globals = globals + # Don't change the indentation of the template; the reindent() calls # in Timer.__init__() depend on setup being indented 4 spaces and stmt # being indented 8 spaces. @@ -94,7 +96,9 @@ class Timer: The constructor takes a statement to be timed, an additional statement used for setup, and a timer function. Both statements default to 'pass'; the timer function is platform-dependent (see - module doc string). + module doc string). If 'globals' is specified, the code will be + executed within that namespace (as opposed to inside timeit's + namespace). To measure the execution time of the first statement, use the timeit() method. The repeat() method is a convenience to call @@ -104,10 +108,12 @@ class Timer: multi-line string literals. """ - def __init__(self, stmt="pass", setup="pass", timer=default_timer): + def __init__(self, stmt="pass", setup="pass", timer=default_timer, + globals=None): """Constructor. See class doc string.""" self.timer = timer - ns = {} + local_ns = {} + global_ns = _globals() if globals is None else globals if isinstance(stmt, str): stmt = reindent(stmt, 8) if isinstance(setup, str): @@ -115,19 +121,19 @@ class Timer: src = template.format(stmt=stmt, setup=setup) elif callable(setup): src = template.format(stmt=stmt, setup='_setup()') - ns['_setup'] = setup + local_ns['_setup'] = setup else: raise ValueError("setup is neither a string nor callable") - self.src = src # Save for traceback display + self.src = src # Save for traceback display code = compile(src, dummy_src_name, "exec") - exec(code, globals(), ns) - self.inner = ns["inner"] + exec(code, global_ns, local_ns) + self.inner = local_ns["inner"] elif callable(stmt): self.src = None if isinstance(setup, str): _setup = setup def setup(): - exec(_setup, globals(), ns) + exec(_setup, global_ns, local_ns) elif not callable(setup): raise ValueError("setup is neither a string nor callable") self.inner = _template_func(setup, stmt) @@ -208,14 +214,14 @@ class Timer: return r def timeit(stmt="pass", setup="pass", timer=default_timer, - number=default_number): + number=default_number, globals=None): """Convenience function to create Timer object and call timeit method.""" - return Timer(stmt, setup, timer).timeit(number) + return Timer(stmt, setup, timer, globals).timeit(number) def repeat(stmt="pass", setup="pass", timer=default_timer, - repeat=default_repeat, number=default_number): + repeat=default_repeat, number=default_number, globals=None): """Convenience function to create Timer object and call repeat method.""" - return Timer(stmt, setup, timer).repeat(repeat, number) + return Timer(stmt, setup, timer, globals).repeat(repeat, number) def main(args=None, *, _wrap_timer=None): """Main program, used when run as a script. |