Closed PFython closed 3 years ago
Peter,
I think the header of this issue is confusing, but I think I understand what you want to achieve. When you decorate the function loop1 or loop2 with @y, it will and should still return the value as returned originally from this function. And when you don't have a return, it is always None. I think changing this behaviour with some parameter would be extremely confusing.
But, there is a rather elegant way to do this type of benchmarking with ycecream, though: Instead of decorating the function put a
y.delta = 0
at the start of the function and at the end
return y.delta
So, the complete code would be
import requests
from ycecream import y
def loop1():
y.delta=0
x = page*count
for i in range(len(x)):
s=len(x)
return y.delta
def loop2():
y.delta=0
x = page*count
lx = len(x)
for i in range(lx):
s = lx
return y.delta
if __name__ == "__main__":
page = requests.get('https://www.bbc.co.uk/news').text
count = 10
for loop in [loop1, loop2]:
results=[]
for run in range(10):
result = loop()
results.append(result)
print(results)
You could even consider tallying the duration in the function itself:
import requests
from ycecream import y
def loop1():
y.delta=0
x = page*count
for i in range(len(x)):
s=len(x)
y.results.append(y.delta)
def loop2():
global results
y.delta=0
x = page*count
lx = len(x)
for i in range(lx):
s = lx
y.results.append(y.delta)
if __name__ == "__main__":
page = requests.get('https://www.bbc.co.uk/news').text
count = 10
for loop in [loop1, loop2]:
y.results = []
for run in range(10):
loop()
print(y.results)
Would that help?
I think there's a more elegant way to solve this problem, by redefining the output function. Then, you don't have to change the loop functions at all. Just a slightly different decorator does the job:
import requests
from ycecream import y
def collect(s):
y.results.append(float(s[-16:-8]))
@y(output=collect, show_enter=False)
def loop1():
x = page*count
for i in range(len(x)):
s=len(x)
@y(output=collect, show_enter=False)
def loop2():
x = page*count
lx = len(x)
for i in range(lx):
s = lx
if __name__ == "__main__":
page = requests.get('https://www.bbc.co.uk/news').text
count = 10
for loop in [loop1, loop2]:
y.results=[]
for run in range(10):
loop()
print(y.results)
And if you would like to use this decorator even on more places without having to repeat the parameters all the time, you could fork a new ycecream instance, like:
y_benchmark = y.fork(output=collect, show_enter=False)
and then decorate with
@y_benchmark()
def loop1():
...
Sweet, eh?
It might look a bit strange that I use y.result to collect the data. But that prevents me from having to use another class or a global variable. Just laziness, you could say.
I'm trying to catch just the 'exit' output with the ultimate goal of calculating and comparing the average run time of two functions (
loop1
andloop2
). When I setshow_exit=True, show_enter=False
the default output to screen is what I want to capture withas_str=True
, but what I get is the default resulty| loop(): None\n
OUTPUT