<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
this is my implementation:</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
```</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
units = {"auto": -1, "s": 1, "ms": 1e3, "μs": 1e6, "ns": 1e9}<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span>def timef(unit="auto", number=1, garcol=True, get_time=False):<br>
</span>
<div>    """A decorator to measure the execution time of a function<br>
</div>
<div><br>
</div>
<div>    Returns the return of the tested function if get_time is False or the<br>
</div>
<div>    execution time in unit if not<br>
</div>
<div><br>
</div>
<div>    unit: one of "ns" (nanoseconds), "μs" (microseconds), "ms" (milliseconds),<br>
</div>
<div>    "s" (seconds) and "auto": (automatic) (default: "auto")<br>
</div>
<div>    garcol: if True enables garbage collection (default: True)<br>
</div>
<div>    get_time: if true return the execution time of the function (default: False)<br>
</div>
<div>    """<br>
</div>
<div>    fun = False<br>
</div>
<div>    if callable(unit):<br>
</div>
<div>        fun = True<br>
</div>
<div>        func = unit<br>
</div>
<div>        unit = "auto"<br>
</div>
<div>    elif unit not in units:<br>
</div>
<div>        raise ValueError(<br>
</div>
<div>            "valid options: "<br>
</div>
<div>            "s(seconds), "<br>
</div>
<div>            "ms(milliseconds), "<br>
</div>
<div>            "μs(microseconds), "<br>
</div>
<div>            "ns(nanoseconds) "<br>
</div>
<div>            "and auto(automatic: default)")<br>
</div>
<div><br>
</div>
<div>    def decorating_function(func):<br>
</div>
<div>        return _wrapper(func, number, units, unit, units[unit], garcol, get_time)<br>
</div>
<div>    return decorating_function(func) if fun else decorating_function<br>
</div>
<div><br>
</div>
<div><br>
</div>
<div>def _wrapper(func, number, units, unit, factor, garcol, get_time):<br>
</div>
<div>    def timed(*args, **kwargs):<br>
</div>
<div>        nonlocal unit, factor<br>
</div>
<div>        gcold = gc.isenabled()<br>
</div>
<div>        # disable garbage collection on demand<br>
</div>
<div>        if not garcol:<br>
</div>
<div>            gc.disable()<br>
</div>
<div>        try:<br>
</div>
<div>            if number > 0:<br>
</div>
<div>                start = default_timer()<br>
</div>
<div>                for _ in range(number):<br>
</div>
<div>                    func(*args, **kwargs)<br>
</div>
<div>                time = default_timer() - start<br>
</div>
<div>                result = func(*args, **kwargs)<br>
</div>
<div>        finally:<br>
</div>
<div>            if gcold:<br>
</div>
<div>                gc.enable()<br>
</div>
<div>        if unit == "auto":<br>
</div>
<div>            for u, f in units.items():<br>
</div>
<div>                if 1 <= int(time * f) < 1000:<br>
</div>
<div>                    unit, factor = u, f<br>
</div>
<div>                    break<br>
</div>
<div>            else:<br>
</div>
<div>                unit, factor = "s", 1<br>
</div>
<div>        time *= factor<br>
</div>
<div>        print(f"{func.__qualname__}: {time:.4f} {unit}")<br>
</div>
<div>        return time if get_time else result<br>
</div>
<span>    return timed</span><br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
```</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
it's not perfect but it works; y<span>ou can control number of repetitions, garbage collection, unit ...<br>
</span>
<div>and it produces a formatted output such as:<br>
</div>
<span>`fun_to_time: 24.1056 ms`.</span></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>De :</b> Python-ideas <python-ideas-bounces+amjadhedhili=outlook.com@python.org> de la part de Steven D'Aprano <steve@pearwood.info><br>
<b>Envoyé :</b> dimanche 7 octobre 2018 04:15<br>
<b>À :</b> python-ideas@python.org<br>
<b>Objet :</b> Re: [Python-ideas] add a time decorator to timeit.py</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">On Sun, Oct 07, 2018 at 10:16:08AM +0000, Amjad Ben Hedhili wrote:<br>
<br>
> I think that a time decorator will be a useful addition to the sandard <br>
> library, as i find the current way of measuring execution time a bit <br>
> tedious:<br>
> <br>
> timeit.timeit("fun_to_time(a, b)", setup="from __main__ import a, b", number=1)<br>
<br>
There are lots of ways to call timeit, but generally if you are calling <br>
it with number=1 then your results may not be trustworthy. (That depends <br>
on the function, of course.) There's a reason why timeit defaults to <br>
number=1000000 rather than 1.<br>
<br>
<br>
> compared to:<br>
> <br>
> @timef<br>
> def fun_to_time(a, b):<br>
>     ...<br>
<br>
The problem with that as an API is that once you have decorated the <br>
function to call timeit, how do you use it *without* calling timeit?<br>
<br>
If you use functools.wraps, there will be a func_to_time.__wrapped__ but <br>
I don't think that calling that directly is a good interface.<br>
<br>
<br>
> or<br>
> <br>
> timef(print)("Hello world!").<br>
> <br>
> I already made a basic implementation of it, and it's working well.<br>
<br>
Can you explain what the timef decorator does? What arguments does it <br>
take, how do we use it?<br>
<br>
<br>
-- <br>
Steve<br>
_______________________________________________<br>
Python-ideas mailing list<br>
Python-ideas@python.org<br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/">http://python.org/psf/codeofconduct/</a><br>
</div>
</span></font></div>
</body>
</html>