Hoe de verstreken tijd in Python meten?

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-functie QueryPerformanceCounter(). 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 daarvan perf_counter() of process_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:

  1. timeit selecteert de beste timer die beschikbaar is voor uw besturingssysteem en Python-versie.
  2. 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:

  1. Gebruik timer van timeit in plaats van time.time om eerder beschreven redenen.
  2. Je kunt GC tijdens de timing uitschakelen als je wilt.
  3. Decorator accepteert functies met benoemde of niet-benoemde parameters.
  4. Mogelijkheid om afdrukken in bloktiming uit te schakelen (gebruik with timing.MeasureBlockTime() as t en vervolgens t.elapsed).
  5. 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:

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:

voer hier de afbeeldingsbeschrijving in

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

LEAVE A REPLY

Please enter your comment!
Please enter your name here

20 + five =

Other episodes