[Python-ideas] add a time decorator to timeit.py
Amjad Ben Hedhili
amjadhedhili at outlook.com
Sun Oct 7 07:43:40 EDT 2018
this is my implementation:
```
units = {"auto": -1, "s": 1, "ms": 1e3, "μs": 1e6, "ns": 1e9}
def timef(unit="auto", number=1, garcol=True, get_time=False):
"""A decorator to measure the execution time of a function
Returns the return of the tested function if get_time is False or the
execution time in unit if not
unit: one of "ns" (nanoseconds), "μs" (microseconds), "ms" (milliseconds),
"s" (seconds) and "auto": (automatic) (default: "auto")
garcol: if True enables garbage collection (default: True)
get_time: if true return the execution time of the function (default: False)
"""
fun = False
if callable(unit):
fun = True
func = unit
unit = "auto"
elif unit not in units:
raise ValueError(
"valid options: "
"s(seconds), "
"ms(milliseconds), "
"μs(microseconds), "
"ns(nanoseconds) "
"and auto(automatic: default)")
def decorating_function(func):
return _wrapper(func, number, units, unit, units[unit], garcol, get_time)
return decorating_function(func) if fun else decorating_function
def _wrapper(func, number, units, unit, factor, garcol, get_time):
def timed(*args, **kwargs):
nonlocal unit, factor
gcold = gc.isenabled()
# disable garbage collection on demand
if not garcol:
gc.disable()
try:
if number > 0:
start = default_timer()
for _ in range(number):
func(*args, **kwargs)
time = default_timer() - start
result = func(*args, **kwargs)
finally:
if gcold:
gc.enable()
if unit == "auto":
for u, f in units.items():
if 1 <= int(time * f) < 1000:
unit, factor = u, f
break
else:
unit, factor = "s", 1
time *= factor
print(f"{func.__qualname__}: {time:.4f} {unit}")
return time if get_time else result
return timed
```
it's not perfect but it works; you can control number of repetitions, garbage collection, unit ...
and it produces a formatted output such as:
`fun_to_time: 24.1056 ms`.
________________________________
De : Python-ideas <python-ideas-bounces+amjadhedhili=outlook.com at python.org> de la part de Steven D'Aprano <steve at pearwood.info>
Envoyé : dimanche 7 octobre 2018 04:15
À : python-ideas at python.org
Objet : Re: [Python-ideas] add a time decorator to timeit.py
On Sun, Oct 07, 2018 at 10:16:08AM +0000, Amjad Ben Hedhili wrote:
> I think that a time decorator will be a useful addition to the sandard
> library, as i find the current way of measuring execution time a bit
> tedious:
>
> timeit.timeit("fun_to_time(a, b)", setup="from __main__ import a, b", number=1)
There are lots of ways to call timeit, but generally if you are calling
it with number=1 then your results may not be trustworthy. (That depends
on the function, of course.) There's a reason why timeit defaults to
number=1000000 rather than 1.
> compared to:
>
> @timef
> def fun_to_time(a, b):
> ...
The problem with that as an API is that once you have decorated the
function to call timeit, how do you use it *without* calling timeit?
If you use functools.wraps, there will be a func_to_time.__wrapped__ but
I don't think that calling that directly is a good interface.
> or
>
> timef(print)("Hello world!").
>
> I already made a basic implementation of it, and it's working well.
Can you explain what the timef decorator does? What arguments does it
take, how do we use it?
--
Steve
_______________________________________________
Python-ideas mailing list
Python-ideas at python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181007/dfa71e1b/attachment.html>
More information about the Python-ideas
mailing list