Wat ik wil is om ergens in mijn code de tijd te gaan tellen en dan de verstreken tijd te krijgen, om de tijd te meten die nodig was om een paar functies uit te voeren. Ik denk dat ik de timeit-module verkeerd gebruik, maar de documenten zijn gewoon verwarrend voor mij.
import timeit
start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)
Antwoord 1, autoriteit 100%
Als u alleen de verstreken wandkloktijd tussen twee punten wilt meten, kunt u time.time()
:
import time
start = time.time()
print("hello")
end = time.time()
print(end - start)
Dit geeft de uitvoeringstijd in seconden.
Een andere optie sinds 3.3 is mogelijk het gebruik van perf_counter
of process_time
, afhankelijk van uw wensen. Vóór 3.3 werd het aanbevolen om time.clock
te (bedankt Amber). Het is momenteel echter verouderd:
Retourneer op Unix de huidige processortijd als een getal met drijvende komma
uitgedrukt in seconden. De precisie, en eigenlijk de definitie zelf
van de betekenis van processortijd , hangt af van die van de C-functie
met dezelfde naam.In Windows retourneert deze functie de wandklokseconden die zijn verstreken sinds de
eerste aanroep van deze functie, als een getal met drijvende komma, gebaseerd op de
Win32-functieQueryPerformanceCounter()
. De resolutie is meestal:
beter dan één microseconde.Verouderd sinds versie 3.3: het gedrag van deze functie hangt af van
op het platform: gebruik in plaats daarvanperf_counter()
ofprocess_time()
,
afhankelijk van uw vereisten, om een goed gedefinieerd gedrag te hebben.
Antwoord 2, autoriteit 47%
Gebruik timeit.default_timer
in plaats van timeit.timeit
. De eerste biedt automatisch de beste klok die beschikbaar is op uw platform en versie van Python:
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 toegewezen aan time.time( ) of time.clock() afhankelijk van het besturingssysteem. Op Python 3.3+ is default_timer time.perf_counter() op alle platforms. Zie Python – time.clock() vs. time.time() – nauwkeurigheid?
Zie ook:
Antwoord 3, autoriteit 9%
Alleen Python 3:
Sinds time.clock() is verouderd vanaf Python 3.3, wilt u time.perf_counter()
voor systeembrede timing, of time.process_time()
voor procesbrede timing, precies zoals u vroeger time.clock()
gebruikte:
import time
t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t
De nieuwe functie process_time
houdt geen rekening met de tijd die is verstreken tijdens de slaap.
Antwoord 4, autoriteit 6%
Tijd meten in seconden:
from timeit import default_timer as timer
from datetime import timedelta
start = timer()
end = timer()
print(timedelta(seconds=end-start))
Uitvoer:
0:00:01.946339
Antwoord 5, autoriteit 5%
Gegeven een functie die u wilt timen,
test.py:
def foo():
# print "hello"
return "hello"
de gemakkelijkste manier om timeit
te gebruiken, is door het vanaf de opdrachtregel aan te roepen:
% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop
Probeer time.time
of time.clock
(naïef) niet te gebruiken om de snelheid van functies te vergelijken. Ze kunnen misleidende resultaten opleveren.
PS. Plaats geen printstatements in een functie die u wilt timen; anders hangt de gemeten tijd af van de snelheid van de terminal.
Antwoord 6, autoriteit 4%
Het is leuk om dit te doen met een context-manager die automatisch de starttijd onthoudt bij binnenkomst in een with
blok, en vervolgens de eindtijd bevriest bij het afsluiten van een blok. Met een beetje bedrog kun je zelfs een lopende verstreken tijd binnen het blok krijgen vanuit dezelfde contextmanager-functie.
De kernbibliotheek heeft dit niet (maar zou dat waarschijnlijk wel moeten doen). Eenmaal op zijn plaats, kunt u dingen doen als:
with elapsed_timer() as elapsed:
# some lengthy code
print( "midpoint at %.2f seconds" % elapsed() ) # time so far
# other lengthy code
print( "all done at %.2f seconds" % elapsed() )
Hier is de contextmanager-code voldoende om het te doen:
from contextlib import contextmanager
from timeit import default_timer
@contextmanager
def elapsed_timer():
start = default_timer()
elapser = lambda: default_timer() - start
yield lambda: elapser()
end = default_timer()
elapser = lambda: end-start
En wat uitvoerbare democode:
import time
with elapsed_timer() as elapsed:
time.sleep(1)
print(elapsed())
time.sleep(2)
print(elapsed())
time.sleep(3)
Houd er rekening mee dat door het ontwerp van deze functie de retourwaarde van elapsed()
wordt bevroren bij het afsluiten van een blok, en dat verdere aanroepen dezelfde duur retourneren (van ongeveer 6 seconden in dit speelgoedvoorbeeld).
Antwoord 7, autoriteit 3%
Ik geef er de voorkeur aan. timeit
doc is veel te verwarrend.
from datetime import datetime
start_time = datetime.now()
# INSERT YOUR CODE
time_elapsed = datetime.now() - start_time
print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))
Let op, er wordt hier niet geformatteerd, ik heb zojuist hh:mm:ss
in de afdruk geschreven zodat men time_elapsed
kan interpreteren
Antwoord 8, autoriteit 3%
Hier is een andere manier om dit te doen:
>> from pytictoc import TicToc
>> t = TicToc() # create TicToc instance
>> t.tic() # Start timer
>> # do something
>> t.toc() # Print elapsed time
Elapsed time is 2.612231 seconds.
Vergeleken met de traditionele manier:
>> from time import time
>> t1 = time()
>> # do something
>> t2 = time()
>> elapsed = t2 - t1
>> print('Elapsed time is %f seconds.' % elapsed)
Elapsed time is 2.612231 seconds.
Installatie:
pip install pytictoc
Raadpleeg de PyPi-pagina voor meer details.
Antwoord 9, autoriteit 3%
Hier zijn mijn bevindingen nadat ik hier veel goede antwoorden heb doorgenomen, evenals een paar andere artikelen.
Ten eerste, als je aan het twijfelen bent tussen timeit
en time.time
, heeft de timeit
twee voordelen:
timeit
selecteert de beste timer die beschikbaar is voor uw besturingssysteem en Python-versie.timeit
schakelt het verzamelen van afval uit, maar dit is niet iets wat u wel of niet wilt.
Het probleem is dat timeit
niet zo eenvoudig te gebruiken is, omdat het moet worden ingesteld en dingen lelijk worden als je een heleboel imports hebt. Idealiter wil je gewoon een decorateur of gebruik je with
blok- en meettijd. Helaas is hiervoor niets ingebouwd, dus je hebt twee opties:
Optie 1: gebruik tijdbudgetbibliotheek
De timebudget is een veelzijdige en zeer eenvoudige bibliotheek die u kunt gebruiken in slechts één regel code na pip installatie.
@timebudget # Record how long this function takes
def my_method():
# my code
Optie 2: Mijn kleine module gebruiken
Ik heb onderstaande kleine hulpprogramma-module voor timing gemaakt met de naam timing.py. Zet dit bestand gewoon in uw project en begin het te gebruiken. De enige externe afhankelijkheid is runstats, wat weer klein is.
Je kunt nu elke functie timen door er een decorateur voor te zetten:
import timing
@timing.MeasureTime
def MyBigFunc():
#do something time consuming
for i in range(10000):
print(i)
timing.print_all_timings()
Als je een deel van de code wilt timen, plaats het dan gewoon in het with
blok:
import timing
#somewhere in my code
with timing.MeasureBlockTime("MyBlock"):
#do something time consuming
for i in range(10000):
print(i)
# rest of my code
timing.print_all_timings()
Voordelen:
Er zijn verschillende half-backed versies in omloop, dus ik wil op enkele hoogtepunten wijzen:
- Gebruik timer van timeit in plaats van time.time om eerder beschreven redenen.
- Je kunt GC tijdens de timing uitschakelen als je wilt.
- Decorator accepteert functies met benoemde of niet-benoemde parameters.
- Mogelijkheid om afdrukken in bloktiming uit te schakelen (gebruik
with timing.MeasureBlockTime() as t
en vervolgenst.elapsed
). - Mogelijkheid om gc ingeschakeld te houden voor bloktiming.
Antwoord 10
Het gebruik van time.time
om de uitvoering te meten, geeft u de algehele uitvoeringstijd van uw opdrachten, inclusief de uitvoeringstijd die door andere processen op uw computer wordt besteed. Het is de tijd die de gebruiker opmerkt, maar is niet goed als je verschillende codefragmenten / algoritmen / functies / …
wilt vergelijken
Meer informatie over timeit
:
Als u meer inzicht wilt in profilering:
- http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
- Hoe kun je een python-script profileren?
Update: ik heb http://pythonhosted.org/line_profiler/ gebruikt veel tijdens het afgelopen jaar en vind het erg nuttig en raad aan om het te gebruiken in plaats van de Pythons-profielmodule.
Antwoord 11
De eenvoudigste manier om de duur van een operatie te berekenen:
import time
start_time = time.monotonic()
<operations, programs>
print('seconds: ', time.monotonic() - start_time)
Officiële documenten hier.
Antwoord 12
De python cProfile- en pstats-modules bieden geweldige ondersteuning voor het meten van de verstreken tijd in bepaalde functies zonder dat er code rond de bestaande functies hoeft te worden toegevoegd.
Bijvoorbeeld als je een python-script hebt timeFunctions.py:
import time
def hello():
print "Hello :)"
time.sleep(0.1)
def thankyou():
print "Thank you!"
time.sleep(0.05)
for idx in range(10):
hello()
for idx in range(100):
thankyou()
Om de profiler uit te voeren en statistieken te genereren voor het bestand dat u gewoon kunt uitvoeren:
python -m cProfile -o timeStats.profile timeFunctions.py
Wat dit doet, is de cProfile-module gebruiken om alle functies in timeFunctions.py te profileren en de statistieken te verzamelen in het timeStats.profile-bestand. Merk op dat we geen code hoefden toe te voegen aan een bestaande module (timeFunctions.py) en dit kan met elke module.
Zodra je het stats-bestand hebt, kun je de pstats-module als volgt uitvoeren:
python -m pstats timeStats.profile
Hierdoor wordt de interactieve statistiekenbrowser uitgevoerd die u veel leuke functionaliteit biedt. Voor uw specifieke gebruiksgeval kunt u gewoon de statistieken voor uw functie controleren. In ons voorbeeld laat het controleren van statistieken voor beide functies ons het volgende zien:
Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp> timeStats.profile
224 function calls in 6.014 seconds
Random listing order was used
List reduced from 6 to 1 due to restriction <'hello'>
ncalls tottime percall cumtime percall filename:lineno(function)
10 0.000 0.000 1.001 0.100 timeFunctions.py:3(hello)
timeStats.profile% stats thankyou
<timestamp> timeStats.profile
224 function calls in 6.014 seconds
Random listing order was used
List reduced from 6 to 1 due to restriction <'thankyou'>
ncalls tottime percall cumtime percall filename:lineno(function)
100 0.002 0.000 5.012 0.050 timeFunctions.py:7(thankyou)
Het dummy-voorbeeld doet niet veel, maar geeft u een idee van wat er gedaan kan worden. Het beste van deze aanpak is dat ik mijn bestaande code niet hoef te bewerken om deze nummers te krijgen en uiteraard hulp bij profilering.
Antwoord 13
Hier is nog een contextmanager voor timingcode –
Gebruik:
from benchmark import benchmark
with benchmark("Test 1+1"):
1+1
=>
Test 1+1 : 1.41e-06 seconds
of, als u de tijdwaarde nodig heeft
with benchmark("Test 1+1") as b:
1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07
benchmark.py:
from timeit import default_timer as timer
class benchmark(object):
def __init__(self, msg, fmt="%0.3g"):
self.msg = msg
self.fmt = fmt
def __enter__(self):
self.start = timer()
return self
def __exit__(self, *args):
t = timer() - self.start
print(("%s : " + self.fmt + " seconds") % (self.msg, t))
self.time = t
Aangepast van http://dabeaz.blogspot. fr/2010/02/context-manager-for-timing-benchmarks.html
Antwoord 14
Hier is een kleine timerklasse die de string “uu:mm:ss” retourneert:
class Timer:
def __init__(self):
self.start = time.time()
def restart(self):
self.start = time.time()
def get_time_hhmmss(self):
end = time.time()
m, s = divmod(end - self.start, 60)
h, m = divmod(m, 60)
time_str = "%02d:%02d:%02d" % (h, m, s)
return time_str
Gebruik:
# Start timer
my_timer = Timer()
# ... do something
# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )
# ... use the timer again
my_timer.restart()
# ... do something
# Get time:
time_hhmmss = my_timer.get_time_hhmmss()
# ... etc
Antwoord 15
Gebruik profiler-module. Het geeft een zeer gedetailleerd profiel.
import profile
profile.run('main()')
het geeft zoiets als:
5 function calls in 0.047 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 :0(exec)
1 0.047 0.047 0.047 0.047 :0(setprofile)
1 0.000 0.000 0.000 0.000 <string>:1(<module>)
0 0.000 0.000 profile:0(profiler)
1 0.000 0.000 0.047 0.047 profile:0(main())
1 0.000 0.000 0.000 0.000 two_sum.py:2(twoSum)
Ik vond het erg informatief.
Antwoord 16
(Alleen met Ipython) kunt u %timeit om de gemiddelde verwerkingstijd te meten:
def foo():
print "hello"
en dan:
%timeit foo()
het resultaat is zoiets als:
10000 loops, best of 3: 27 µs per loop
Antwoord 17
Ik vind het eenvoudig leuk (python 3):
from timeit import timeit
timeit(lambda: print("hello"))
Uitvoer is microseconden voor een enkele uitvoering:
2.430883963010274
Uitleg:
timeit voert de anonieme functie standaard 1 miljoen keer uit en het resultaat wordt gegeven in seconden. Daarom is het resultaat voor 1 enkele uitvoering hetzelfde aantal, maar gemiddeld in microseconden.
Voeg voor trage bewerkingen een lager aantal iteraties toe, anders zou u eeuwig kunnen wachten:
import time
timeit(lambda: time.sleep(1.5), number=1)
Uitvoer is altijd in seconden voor het totale aantal iteraties:
1.5015795179999714
Antwoord 18
op python3:
from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)
elegant en kort.
Antwoord 19
Nog een manier om timeit te gebruiken:
from timeit import timeit
def func():
return 1 + 1
time = timeit(func, number=1)
print(time)
Antwoord 20
Als u recursief inzicht wilt krijgen in elke functieaanroep, doet u het volgende:
%load_ext snakeviz
%%snakeviz
Er zijn gewoon die 2 regels code nodig in een Jupyter-notebook en het genereert een mooi interactief diagram. Bijvoorbeeld:
Hier is de code. Nogmaals, de 2 regels die beginnen met %
zijn de enige extra regels code die nodig zijn om snakeviz te gebruiken:
# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib
%%snakeviz
files = glob.glob('*.txt')
def print_files_hashed(files):
for file in files:
with open(file) as f:
print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)
Het lijkt ook mogelijk om snakeviz buiten notebooks uit te voeren. Meer info op de snakeviz-website.
Antwoord 21
Een soort super latere reactie, maar misschien heeft iemand er iets aan. Dit is een manier om het te doen waarvan ik denk dat het super schoon is.
import time
def timed(fun, *args):
s = time.time()
r = fun(*args)
print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
return(r)
timed(print, "Hello")
Houd er rekening mee dat “print” een functie is in Python 3 en niet in Python 2.7. Het werkt echter met elke andere functie. Proost!
Antwoord 22
Hier is een redelijk goed gedocumenteerde en volledig type hintende decorateur die ik als algemeen hulpprogramma gebruik:
from functools import wraps
from time import perf_counter
from typing import Any, Callable, Optional, TypeVar, cast
F = TypeVar("F", bound=Callable[..., Any])
def timer(prefix: Optional[str] = None, precision: int = 6) -> Callable[[F], F]:
"""Use as a decorator to time the execution of any function.
Args:
prefix: String to print before the time taken.
Default is the name of the function.
precision: How many decimals to include in the seconds value.
Examples:
>>> @timer()
... def foo(x):
... return x
>>> foo(123)
foo: 0.000...s
123
>>> @timer("Time taken: ", 2)
... def foo(x):
... return x
>>> foo(123)
Time taken: 0.00s
123
"""
def decorator(func: F) -> F:
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
nonlocal prefix
prefix = prefix if prefix is not None else f"{func.__name__}: "
start = perf_counter()
result = func(*args, **kwargs)
end = perf_counter()
print(f"{prefix}{end - start:.{precision}f}s")
return result
return cast(F, wrapper)
return decorator
Voorbeeld van gebruik:
from timer import timer
@timer(precision=9)
def takes_long(x: int) -> bool:
return x in (i for i in range(x + 1))
result = takes_long(10**8)
print(result)
Uitvoer:
takes_long: 4.942629056s True
De doctests kunnen worden gecontroleerd met:
$ python3 -m doctest --verbose -o=ELLIPSIS timer.py
En het type hints met:
$ mypy timer.py
Antwoord 23
U kunt timeit gebruiken.
Hier is een voorbeeld van het testen van naive_func die een parameter nodig heeft met Python REPL:
>>> import timeit
>>> def naive_func(x):
... a = 0
... for i in range(a):
... a += i
... return a
>>> def wrapper(func, *args, **kwargs):
... def wrapper():
... return func(*args, **kwargs)
... return wrapper
>>> wrapped = wrapper(naive_func, 1_000)
>>> timeit.timeit(wrapped, number=1_000_000)
0.4458435332577161
U hebt geen wrapper-functie nodig als de functie geen parameters heeft.
Antwoord 24
We kunnen tijd ook omzetten in door mensen leesbare tijd.
import time, datetime
start = time.clock()
def num_multi1(max):
result = 0
for num in range(0, 1000):
if (num % 3 == 0 or num % 5 == 0):
result += num
print "Sum is %d " % result
num_multi1(1000)
end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')
Antwoord 25
print_elapsed_time functie staat hieronder
def print_elapsed_time(prefix=''):
e_time = time.time()
if not hasattr(print_elapsed_time, 's_time'):
print_elapsed_time.s_time = e_time
else:
print(f'{prefix} elapsed time: {e_time - print_elapsed_time.s_time:.2f} sec')
print_elapsed_time.s_time = e_time
gebruik het op deze manier
print_elapsed_time()
.... heavy jobs ...
print_elapsed_time('after heavy jobs')
.... tons of jobs ...
print_elapsed_time('after tons of jobs')
resultaat is
after heavy jobs elapsed time: 0.39 sec
after tons of jobs elapsed time: 0.60 sec
de voor- en nadelen van deze functie zijn dat je de starttijd niet hoeft te overschrijden
Antwoord 26
Ik heb hiervoor een bibliotheek gemaakt, als je een functie wilt meten, kun je dat gewoon zo doen
from pythonbenchmark import compare, measure
import time
a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]
@measure
def myFunction(something):
time.sleep(0.4)
@measure
def myOptimizedFunction(something):
time.sleep(0.2)
myFunction(input)
myOptimizedFunction(input)
https://github.com/Karlheinzniebuhr/pythonbenchmark
Antwoord 27
Hoe de tijd tussen twee bewerkingen te meten. Vergelijk de tijd van twee bewerkingen.
import time
b = (123*321)*123
t1 = time.time()
c = ((9999^123)*321)^123
t2 = time.time()
print(t2-t1)
7.987022399902344e-05
Antwoord 28
Hoewel het niet strikt in de vraag wordt gesteld, is het vaak zo dat u een eenvoudige, uniforme manier wilt om de verstreken tijd tussen verschillende regels code stapsgewijs te meten.
Als u Python 3.8 of hoger gebruikt, kunt u gebruik maken van toewijzingsexpressies (ook bekend als de walrus-operator) om dit op een redelijk elegante manier te bereiken:
import time
start, times = time.perf_counter(), {}
print("hello")
times["print"] = -start + (start := time.perf_counter())
time.sleep(1.42)
times["sleep"] = -start + (start := time.perf_counter())
a = [n**2 for n in range(10000)]
times["pow"] = -start + (start := time.perf_counter())
print(times)
=>
{'print': 2.193450927734375e-05, 'sleep': 1.4210970401763916, 'power': 0.005671024322509766}
Antwoord 29
import time
def getElapsedTime(startTime, units):
elapsedInSeconds = time.time() - startTime
if units == 'sec':
return elapsedInSeconds
if units == 'min':
return elapsedInSeconds/60
if units == 'hour':
return elapsedInSeconds/(60*60)
Antwoord 30
Deze unieke, op klassen gebaseerde benadering biedt een afdrukbare tekenreeksweergave, aanpasbare afronding en gemakkelijke toegang tot de verstreken tijd als tekenreeks of float. Het is ontwikkeld met Python 3.7.
import datetime
import timeit
class Timer:
"""Measure time used."""
# Ref: https://stackoverflow.com/a/57931660/
def __init__(self, round_ndigits: int = 0):
self._round_ndigits = round_ndigits
self._start_time = timeit.default_timer()
def __call__(self) -> float:
return timeit.default_timer() - self._start_time
def __str__(self) -> str:
return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))
Gebruik:
# Setup timer
>>> timer = Timer()
# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.
# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425