Patch #1533909: the timeit module now accepts callables in addition to

strings for the code to time and the setup code. Also added two
convenience functions for instantiating a Timer and calling its methods.
This commit is contained in:
Georg Brandl 2007-03-13 19:32:21 +00:00
parent 4168c0466f
commit d9bef35e3c
4 changed files with 83 additions and 11 deletions

View File

@ -31,6 +31,13 @@ To measure the execution time of the first statement, use the
\method{timeit()} method. The \method{repeat()} method is a \method{timeit()} method. The \method{repeat()} method is a
convenience to call \method{timeit()} multiple times and return a list convenience to call \method{timeit()} multiple times and return a list
of results. of results.
\versionchanged[The \var{stmt} and \var{setup} parameters can now also
take objects that are callable without arguments. This
will embed calls to them in a timer function that will
then be executed by \method{timeit()}. Note that the timing
overhead is a little larger in this case because of the
extra function calls]{2.6}
\end{classdesc} \end{classdesc}
\begin{methoddesc}{print_exc}{\optional{file=\constant{None}}} \begin{methoddesc}{print_exc}{\optional{file=\constant{None}}}
@ -97,6 +104,24 @@ measured. If so, GC can be re-enabled as the first statement in the
\end{methoddesc} \end{methoddesc}
Starting with version 2.6, the module also defines two convenience functions:
\begin{funcdesc}{repeat}{stmt\optional{, setup\optional{, timer\optional{,
repeat\code{=3} \optional{, number\code{=1000000}}}}}}
Create a \class{Timer} instance with the given statement, setup code and timer
function and run its \method{repeat} method with the given repeat count and
\var{number} executions.
\versionadded{2.6}
\end{funcdesc}
\begin{funcdesc}{timeit}{stmt\optional{, setup\optional{, timer\optional{,
number\code{=1000000}}}}}
Create a \class{Timer} instance with the given statement, setup code and timer
function and run its \method{timeit} method with \var{number} executions.
\versionadded{2.6}
\end{funcdesc}
\subsection{Command Line Interface} \subsection{Command Line Interface}
When called as a program from the command line, the following form is used: When called as a program from the command line, the following form is used:

View File

@ -90,6 +90,17 @@ def reindent(src, indent):
"""Helper to reindent a multi-line statement.""" """Helper to reindent a multi-line statement."""
return src.replace("\n", "\n" + " "*indent) return src.replace("\n", "\n" + " "*indent)
def _template_func(setup, func):
"""Create a timer function. Used if the "statement" is a callable."""
def inner(_it, _timer):
setup()
_t0 = _timer()
for _i in _it:
func()
_t1 = _timer()
return _t1 - _t0
return inner
class Timer: class Timer:
"""Class for timing execution speed of small code snippets. """Class for timing execution speed of small code snippets.
@ -109,14 +120,32 @@ class Timer:
def __init__(self, stmt="pass", setup="pass", timer=default_timer): def __init__(self, stmt="pass", setup="pass", timer=default_timer):
"""Constructor. See class doc string.""" """Constructor. See class doc string."""
self.timer = timer self.timer = timer
stmt = reindent(stmt, 8)
setup = reindent(setup, 4)
src = template % {'stmt': stmt, 'setup': setup}
self.src = src # Save for traceback display
code = compile(src, dummy_src_name, "exec")
ns = {} ns = {}
exec code in globals(), ns if isinstance(stmt, basestring):
self.inner = ns["inner"] stmt = reindent(stmt, 8)
if isinstance(setup, basestring):
setup = reindent(setup, 4)
src = template % {'stmt': stmt, 'setup': setup}
elif callable(setup):
src = template % {'stmt': stmt, 'setup': '_setup()'}
ns['_setup'] = setup
else:
raise ValueError("setup is neither a string nor callable")
self.src = src # Save for traceback display
code = compile(src, dummy_src_name, "exec")
exec code in globals(), ns
self.inner = ns["inner"]
elif callable(stmt):
self.src = None
if isinstance(setup, basestring):
_setup = setup
def setup():
exec _setup in globals(), ns
elif not callable(setup):
raise ValueError("setup is neither a string nor callable")
self.inner = _template_func(setup, stmt)
else:
raise ValueError("stmt is neither a string nor callable")
def print_exc(self, file=None): def print_exc(self, file=None):
"""Helper to print a traceback from the timed code. """Helper to print a traceback from the timed code.
@ -136,10 +165,13 @@ class Timer:
sent; it defaults to sys.stderr. sent; it defaults to sys.stderr.
""" """
import linecache, traceback import linecache, traceback
linecache.cache[dummy_src_name] = (len(self.src), if self.src is not None:
None, linecache.cache[dummy_src_name] = (len(self.src),
self.src.split("\n"), None,
dummy_src_name) self.src.split("\n"),
dummy_src_name)
# else the source is already stored somewhere else
traceback.print_exc(file=file) traceback.print_exc(file=file)
def timeit(self, number=default_number): def timeit(self, number=default_number):
@ -189,6 +221,16 @@ class Timer:
r.append(t) r.append(t)
return r return r
def timeit(stmt="pass", setup="pass", timer=default_timer,
number=default_number):
"""Convenience function to create Timer object and call timeit method."""
return Timer(stmt, setup, timer).timeit(number)
def repeat(stmt="pass", setup="pass", timer=default_timer,
repeat=default_repeat, number=default_number):
"""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):
"""Main program, used when run as a script. """Main program, used when run as a script.

View File

@ -156,6 +156,7 @@ Ben Darnell
Jonathan Dasteel Jonathan Dasteel
John DeGood John DeGood
Vincent Delft Vincent Delft
Erik Demaine
Roger Dev Roger Dev
Toby Dickenson Toby Dickenson
Yves Dionne Yves Dionne

View File

@ -168,6 +168,10 @@ Core and builtins
Library Library
------- -------
- Patch #1533909: the timeit module now accepts callables in addition to
strings for the code to time and the setup code. Also added two
convenience functions for instantiating a Timer and calling its methods.
- Patch #1537850: tempfile.NamedTemporaryFile now has a "delete" parameter - Patch #1537850: tempfile.NamedTemporaryFile now has a "delete" parameter
which can be set to False to prevent the default delete-on-close which can be set to False to prevent the default delete-on-close
behavior. behavior.