The magic command %timeit
is not made to be used in a script.
In Use Python's `timeit` from a program but functioning the same way as the command line?, the following function was proposed by the user Unutbu:
import timeit
def timeit_auto(stmt="pass", setup="pass", repeat=3):
"""
https://mcmap.net/q/110010/-use-python-39-s-timeit-from-a-program-but-functioning-the-same-way-as-the-command-line/190597 (endolith)
Imitate default behavior when timeit is run as a script.
Runs enough loops so that total execution time is greater than 0.2 sec,
and then repeats that 3 times and keeps the lowest value.
Returns the number of loops and the time for each loop in microseconds
"""
t = timeit.Timer(stmt, setup)
# determine number so that 0.2 <= total time < 2.0
for i in range(1, 10):
number = 10**i
x = t.timeit(number) # seconds
if x >= 0.2:
break
r = t.repeat(repeat, number)
best = min(r)
usec = best * 1e6 / number
return number, usec
Which can be used as follows:
import timeit
import utils_timeit as UT
def foo():
total = 0
for i in range(10000):
total += i**3
return total
num, timing = UT.timeit_auto(setup='from __main__ import foo', stmt='foo()')
print(num, timing)
Which is a very smart and handy solution. However, I am looking for a even better way. I don't want to give a setup
statement to the function, I think it is very obnoxious. If I have a dataframe df
and a column name column_name_a
, I don't want to have to explicitly state setup='from __main__ import df, column_name_a'
whenever I want to time an operation to df[column_name_a]
.
Is there a nice way to fix it? I did it myself by adding this to the function, such that all the variables that are required are added to the setup statement in a loop by catching errors:
condition = True
setup = 'from __main__ import _'
while condition:
try:
t = timeit.Timer(stmt, setup)
t.repeat(repeat, number)
condition = False
except NameError as err:
str_err = str(err)
extra_import = str_err.split(sep="'")[1]
setup = setup + ', ' + extra_import
this is ofcourse not a very subtle solution. Does anyone have a better approach?
Furthermore, in the same thread (Use Python's `timeit` from a program but functioning the same way as the command line?), someone proposed to use the Timer.autorange
method. I am not sure how to include this in the function. Can anyone help me with that?