How to measure elapsed time in Python?
Solution 1
Use time.time()
to measure the elapsed wall-clock time between two points:
import time
start = time.time()
print("hello")
end = time.time()
print(end - start)
This gives the execution time in seconds.
Another option since Python 3.3 might be to use perf_counter
or process_time
, depending on your requirements. Before 3.3 it was recommended to use time.clock
(thanks Amber). However, it is currently deprecated:
On Unix, return the current processor time as a floating point number expressed in seconds. The precision, and in fact the very definition of the meaning of “processor time”, depends on that of the C function of the same name.
On Windows, this function returns wall-clock seconds elapsed since the first call to this function, as a floating point number, based on the Win32 function
QueryPerformanceCounter()
. The resolution is typically better than one microsecond.Deprecated since version 3.3: The behaviour of this function depends on the platform: use
perf_counter()
orprocess_time()
instead, depending on your requirements, to have a well defined behaviour.
Solution 2
Use timeit.default_timer
instead of timeit.timeit
. The former provides the best clock available on your platform and version of Python automatically:
from timeit import default_timer as timer
start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282
timeit.default_timer is assigned to time.time() or time.clock() depending on OS. On Python 3.3+ default_timer is time.perf_counter() on all platforms. See Python - time.clock() vs. time.time() - accuracy?
See also:
Solution 3
Python 3 only:
Since time.clock()
is deprecated as of Python 3.3, you will want to use time.perf_counter()
for system-wide timing, or time.process_time()
for process-wide timing, just the way you used to use time.clock()
:
import time
t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t
The new function process_time
will not include time elapsed during sleep.
Solution 4
Measuring time in seconds:
from timeit import default_timer as timer
from datetime import timedelta
start = timer()
# ....
# (your code runs here)
# ...
end = timer()
print(timedelta(seconds=end-start))
Output:
0:00:01.946339
Solution 5
Given a function you'd like to time,
test.py:
def foo():
# print "hello"
return "hello"
the easiest way to use timeit
is to call it from the command line:
% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop
Do not try to use time.time
or time.clock
(naively) to compare the speed of functions. They can give misleading results.
PS. Do not put print statements in a function you wish to time; otherwise the time measured will depend on the speed of the terminal.
gilbert8
Updated on July 08, 2022Comments
-
gilbert8 almost 2 years
What I want is to start counting time somewhere in my code and then get the passed time, to measure the time it took to execute few function. I think I'm using the timeit module wrong, but the docs are just confusing for me.
import timeit start = timeit.timeit() print("hello") end = timeit.timeit() print(end - start)
-
Llopeth about 3 yearstimeit.timeit() prints the time that it takes to execute its argument, which is "pass" by default. you have to instead use start= time.time() end = time.time()
-
-
Inca over 12 yearsand for microseconds, use datetime.time()
-
Amber over 12 years(For performance measurement,
time.clock()
is actually preferred, since it can't be interfered with if the system clock gets messed with, but.time()
does mostly accomplish the same purpose.) -
Visgean Skeloru over 10 yearsI think that python -mtimeit is way better as it runs more times and it is build as a native way to measure time in python
-
sidgeon smythe about 10 yearsAll this is fine, but AFAICT this still measures CPU time, not wall clock time.
-
sidgeon smythe about 10 yearsActually there is some confusion; it appears cProfile does look at wall-clock time by default. I've upvoted your answer.
-
jfs over 9 yearsUse
timeit.default_timer
instead oftime.perf_counter
. The former will choose the appropriate timer to measure the time performance tuned for your platform and Python version.process_time()
does not include the time during sleep and therefore it is not appropriate to measure elapsed time. -
Danijel over 8 yearsIs there a nice way of converting resulting execturion time in seconds to something like HH:MM::SS?
-
jfs about 8 years@Amber:
time.clock()
meaning (what is measured) and its accuracy and precision (resolution) differ between platforms. The docs no longer recommendtime.clock()
for benchmarking.timeit.default_timer()
could be used instead. -
jfs about 8 years@Danijel:
print(timedelta(seconds=execution_time))
. Though it is a separate question. -
Jérôme about 8 yearsOther context manager example: dabeaz.blogspot.fr/2010/02/…
-
AlejandroVD about 8 yearstime.clock() didnt work for me. See the timeit answer by @J.F.Sebastian
-
ugotchi almost 8 yearsI'm using the implementation suggested by Pierre, are the values given in seconds?
-
lkgarrison over 7 yearsExcellent answer - using timeit will produce far more accurate results since it will automatically account for things like garbage collection and OS differences
-
raacer over 7 yearsIt worth to mention it is possible to pass flags to %timeit, for example -n specifies how many times the code should be repeated.
-
Brian Burns over 7 years@Jérôme nice example - I adapted it as another answer - stackoverflow.com/a/41408510/243392
-
Katie over 7 yearsThis gives time in ms or seconds?
-
jfs over 7 years@KhushbooTiwari in fractional seconds.
-
KGS almost 7 yearsI think this note from the official documentation needs to be added
default_timer() measurations can be affected by other programs running on the same machine, so the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The -r option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use time.clock() to measure CPU time.
-
jfs almost 7 years@KGS: Performance measurement is very tricky in a subtle way (it is easy to mislead yourself). There are many other remarks that could be relevant here. Follow the links in the answer. You might be also interested in the
perf
module (nonexistent at the time of the answer) that provides the same interface but it sometimes makes different from thetimeit
module decisions about how to measure time performance. -
Reddspark almost 7 yearsI prefer this. Timeit doc is far too confusing.
from datetime import datetime startTime= datetime.now() # INSERT YOUR CODE timeElapsed=datetime.now()-startTime print('Time elpased (hh:mm:ss.ms) {}'.format(timeElapsed))
-
Basil Musa over 6 yearsI dont like how the import took place. "from timeit import default_timer as timer". Got lost while reading the code. Could have been clearer without having the "as timer" part.
-
Otieno Rowland over 6 yearsHow can I print very small times? I kind of am getting 0.0sec always
-
Sreehari R over 6 yearsI was told that timeit calculates the CPU time, does datetime also take into account CPU time used? Are these the same thing?
-
Ciro Santilli OurBigBook.com over 5 yearsA
lambda
would be more succinct:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
-
not2qubit over 5 yearsWhat is
main()
? Would be more useful if you could provide a simple code example. -
Daniel Moskovich over 5 yearsYou can turn this into a decorator; this looks even better to me.
-
JayRizzo over 5 yearsFYI: If you get
python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code)
check your python version you are running. I got this when i ranpython3 -m cProfile...
andpython -m pstats
. My mistake but got me for a second, so, I wanted to sharedon't forget consistency
. =) -
noah almost 5 yearstime.clock() is deprecated at of Python 3.3 docs.python.org/3.3/library/time.html#time.clock
-
hlg almost 5 yearsIt would be good to explain the advantage of using this library over other approaches.
-
PetarMI almost 5 yearsThe nested functionality is actually broken. I opened an issue describing where the problem in the code is but the repo hasn't been maintained in a year so I wouldn't expect a change.
-
user1318499 almost 5 yearsIt's risky to measure elapsed time this way because datetime.now() can change between the two calls for reasons like network time syncing, daylight savings switchover or the user twiddling the clock.
-
Franklin Piat almost 5 yearsThis answer seems off-topic (well, the question wasn't very specific). There are two "time" measurement : wall-clock time between two points, of the cpu consumption of the process.
-
RoG over 4 years@VisgeanSkeloru But sometimes you simply want the time that a particular command took in a particular instance, rather than profiling. Running it n times to get more accuracy takes n times longer after all. What is "better" depends on the situation.
-
KIC over 4 yearswhat is this? ms?
-
ScottieB over 4 yearsI find the nesting a little confusing. If I were to come across
t.tic()
buried in the code, it's up to me the developer to keep a mental list of where in the series I should expect this to be. Do you find yourself setting up nests or just multiple tictocs? -
Tapomay over 4 yearsConcise lambda: ``` lang-python from timeit import default_timer as timer timed = lambda f, s=None: (f(), round(timer() - s, 3)) if s else timed(f, timer()) (result, elapsed) = timed(some_function) ```
-
H. Sánchez about 4 years@PetarMI : FYI, I just fixed the issue with
ttictoc
. Quite a mess I had, but it should be good now. -
Dave Liu about 4 yearsThis is the most concise answer with the cleanest output.
-
xjcl about 4 years
time.time()
is a bad idea because the system clock can be reset which will make you go back in time.time.monotonic()
takes care of this (monotonic = it only goes forward).time.perf_counter()
is also monotonic but has even higher accuracy, so this is recommended for wall-clock time. -
Danny almost 4 yearsThis is super cool, thank you for sharing. I have not encountered the typing library or the nonlocal keyword -- fun to find new things to learn about. I'm having trouble wrapping my head around this:
Callable[[AnyF], AnyF]
. What does it mean? -
ruohola almost 4 years@Danny On the top I've defined the type alias
AnyF
to meanCallable[..., Any]
, soAnyF
is a function that can take any amount of any type arguments and return anything. SoCallable[[AnyF], AnyF]
would expand toCallable[[Callable[..., Any]], Callable[..., Any]]
. This is the type of the return value oftimer
aka the full type ofdecorator
. It is a function that takes any kind of function as its only argument and returns any kind of function. -
Danny almost 4 yearsThanks for the explanation! I'm still trying to fully wrap my head around the internals of decorators. This helped a lot!
-
Guimoute almost 4 years@KIC It's in seconds.
-
user1318499 almost 4 yearsDon't do this because
time.time()
doesn't necessarily increment uniformly. You can get a negative duration if there's a daylight savings adjustment or whatever. Replacetime.time()
withtime.monotonic()
. -
mic almost 4 yearsFrom Shital Shah's answer: "First, if you are debating between timeit and time.time, the timeit has two advantages: timeit selects the best timer available on your OS and Python version. timeit disables garbage collection, however, this is not something you may or may not want."
-
mic almost 4 yearsRegarding "Ability to disable printing in block timing (use
with utils.MeasureBlockTime() as t
and thent.elapsed
).": this doesn't work as is, ast
isNone
. I think__enter__
needs to returnself
, and to disable printing, we have to construct it asutils.MeasureBlockTime(no_print=True)
. -
Shital Shah almost 4 years@mic - thanks for pointing this out. I've updated the answer with this and several other enhancements.
-
frakman1 almost 4 yearsIs there a Python2.x way of doing this without having to import
print_function
from__future__
? I tried to usejoin
but I don't understand it well enough to get it to work. -
frakman1 almost 4 yearsUPDATE. I figured it out and used this:
print(''.join(["time elapsed in ",(func.__name__),": ",str(end - start)]))
-
Harry Moreno over 3 yearswhat do you mean by output? does timeit write to stdout?
-
David over 3 yearsNop. I mean the returned value.
-
Henri over 3 years@hlg If I remember correctly, MATLAB uses functions with similar names to time stuff. So I guess the advantage is the resemblance, for people who liked this in MATLAB but switched to Python.
-
thepunitsingh over 3 yearsThe function
time.clock()
has been removed, after having been deprecated since Python 3.3.time.perf_counter()
ortime.process_time()
can be used instead. Ref: stackoverflow.com/a/58569410/6701627 -
howdoicode over 3 yearsAnd now with f-strings and
format specifications
included:time_str = f"{h:02d}:{m:02d}:{s:02d}"
-
ruohola over 3 years@fjs
timeit.default_timer
usestime.perf_counter
in Python >=3.3 docs.python.org/3/library/timeit.html#timeit.default_timer -
Paolo about 3 years@user1318499 it's not that it returns negative values, it can return a lower value than a previous call. docs.python.org/3/library/time.html#time.time
-
Vega over 2 yearselapsed_time return 0.07812 for example. How do I interpret that? Would a second be 1.000 so my script ran in 7,812 milliseconds?
-
MEMark over 2 yearsI can't get this to work.
unsupported operand type(s) for -: 'datetime.datetime' and 'function'
-
ingyhere over 2 years@MEMark Uncertainty here without seeing the code, but note that this was made for Python 3. The error means a the wrong datatype is being used in place of a
datetime
object. Could the code be tryingt_diff(t_diff())
ort_diff(t())
instead oft_diff(t)
(wheret
is a scalar set earlier ast = t_set()
)? -
alexsmail over 2 yearsIt is better to use
time.monotonic_ns()
, see docs.python.org/3/library/time.html#time.monotonic_ns -
Dan Nissenbaum over 2 yearsThis is simple and excellent - easy to code; I'm surprised that (a) this kind of functionality isn't present in ANY of the existing Python profilers; and (b) that this answer, including a simple class that can be copied-and-pasted, wasn't offered to this question years ago with many more upvotes.
-
Will Croxford over 2 yearseasy to read, easy to use, accurate enough for approx tests or comparisons. But, as I cannot seem to edit at time of writing, to, 'compare the time of two operations', this should have
t0 = time.time()
I feel after import line. Thenprint(t1 -t0)
is first operation time. 2 times are needed to compare 2 operations. -
NeilG about 2 yearsYes, @BasilMusa, I don't know why peeps sometimes like to rename canonical library identifiers, especially to something that is identical to another canonical library identiier altogether! Talk about generating deliberate ambiguity. Just to reduce line length? Perhaps they're still struggling with the ridiculous 80 character line limit, for when peeps used to have vewy vewy small monitors. Just hike it to 120. I recommend 160, oh yeah!
-
jfs almost 2 years@NeilG part of the
import
functionality acts like=
as inx=1
.timer
is used for the same reasonx
may be used instead of1
. Think about it. -
NeilG almost 2 yearsI'm supporting Basil Musa's objection, @jfs, your objection is not clear. To demonstrate, we could make it worse by using
from timeit import default_timer as os
. Even shorter, but catastrophically misleading. Importing astimer
is misleading, to wit, it misled Basil, and I concur.from timeit import default_timer
is clearer. Some recommend (may be in a PEP can't remember)import timeit
and then usetimeit.default_timer
, maximum clarity. That could be overkill but why add a different identifier, especially one that collides with an identifier from another popular module?