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....@python.org> de la part de Steven D'Aprano <st...@pearwood.info> Envoyé : dimanche 7 octobre 2018 04:15 À : python-ideas@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@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/