mirror of https://github.com/python/cpython
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:
parent
4168c0466f
commit
d9bef35e3c
|
@ -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:
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue