Jak mierzyć upływ czasu w Pythonie?


1206

Chcę rozpocząć odliczanie czasu gdzieś w moim kodzie, a następnie uzyskać upływ czasu, aby zmierzyć czas potrzebny do wykonania kilku funkcji. Myślę, że źle używam modułu timeit, ale dokumenty są dla mnie mylące.

import timeit

start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)

Odpowiedzi:


1452

Jeśli chcesz tylko zmierzyć upływający czas zegara ściennego między dwoma punktami, możesz użyć time.time():

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

Daje to czas wykonania w sekundach.

Inną opcją od wersji 3.3 może być użycie perf_counterlub process_time, w zależności od wymagań. Przed wersją 3.3 zalecono użycie time.clock(dzięki Amber ). Jednak obecnie jest przestarzałe:

W systemie Unix zwróć bieżący czas procesora jako liczbę zmiennoprzecinkową wyrażoną w sekundach. Precyzja, a właściwie sama definicja znaczenia „czasu procesora”, zależy od funkcji C o tej samej nazwie.

W systemie Windows funkcja ta zwraca sekundy zegara, które upłynęły od pierwszego wywołania tej funkcji, jako liczbę zmiennoprzecinkową, opartą na funkcji Win32 QueryPerformanceCounter(). Rozdzielczość jest zwykle lepsza niż jedna mikrosekunda.

Przestarzałe od wersji 3.3 : Zachowanie tej funkcji zależy od platformy: użyj perf_counter()lub process_time()zamiast tego , w zależności od wymagań, aby mieć dobrze zdefiniowane zachowanie.


17
a przez mikrosekundy użyj datetime.time ()
Inca

110
(W time.clock()rzeczywistości jest preferowany do pomiaru wydajności , ponieważ nie można go zakłócać, jeśli zostanie zepsuty zegar systemowy, ale w .time()większości osiąga ten sam cel.)
Amber

4
Myślę, że python -mtimeit jest znacznie lepszy, ponieważ działa więcej razy i jest budowany jako natywny sposób mierzenia czasu w pythonie
Visgean Skeloru

4
Czy istnieje dobry sposób na konwersję uzyskanego czasu egzekucji w sekundach na coś takiego jak HH: MM :: SS?
Danijel

12
@Danijel: print(timedelta(seconds=execution_time)). Chociaż jest to osobne pytanie.
jfs

687

Użyj timeit.default_timerzamiast timeit.timeit. Ten pierwszy zapewnia najlepszy zegar dostępny na twojej platformie i automatycznie w wersji 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 jest przypisany do time.time () lub time.clock () w zależności od systemu operacyjnego. W Pythonie 3.3+ default_timer to time.perf_counter () na wszystkich platformach. Zobacz Python - time.clock () vs. time.time () - dokładność?

Zobacz też:


28
Doskonała odpowiedź - użycie timeit da znacznie dokładniejsze wyniki, ponieważ automatycznie uwzględni takie rzeczy, jak zbieranie śmieci i różnice w systemie operacyjnym
lkgarrison

1
To daje czas w ms lub sekundach?
Katie

3
@ KhushbooTiwari w ułamkach sekund.
jfs

5
Myślę, że należy dodać tę notatkę z oficjalnej dokumentacjidefault_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.
KGS

1
@KGS: Pomiar wydajności jest bardzo trudny w subtelny sposób (łatwo się zwieść). Istnieje wiele innych uwag, które mogą być istotne tutaj. Postępuj zgodnie z linkami w odpowiedzi. Możesz być także zainteresowany perfmodułem (nieistniejącym w momencie udzielenia odpowiedzi), który zapewnia ten sam interfejs, ale czasami różni się od timeitdecyzji modułu o tym, jak mierzyć wydajność czasową.
jfs,

129

Tylko Python 3:

Ponieważ time.clock () jest przestarzałe od wersji Python 3.3 , będziesz chciał używać time.perf_counter()do pomiaru time.process_time()czasu w całym systemie lub w czasie, tak jak kiedyś time.clock():

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

Nowa funkcja process_timenie będzie obejmować czasu, który upłynął podczas snu.


28
Użyjtimeit.default_timer zamiast time.perf_counter. Ten pierwszy wybierze odpowiedni licznik czasu, aby zmierzyć wydajność czasu dostosowaną do twojej platformy i wersji Pythona. process_time()robi nie obejmuje czasu podczas snu, a zatem nie jest właściwe do pomiaru upływu czasu.
jfs

2
Korzystam z implementacji zaproponowanej przez Pierre'a, czy wartości podano w sekundach?
ugotchi,

Ta odpowiedź wydaje się nie na temat (cóż, pytanie nie było zbyt szczegółowe). Istnieją dwa pomiary „czasu”: zegar ścienny między dwoma punktami zużycia procesora przez procesor.
Franklin Piat

87

Biorąc pod uwagę funkcję, którą chcesz ustawić czas,

test.py:

def foo(): 
    # print "hello"   
    return "hello"

najłatwiejszym sposobem timeitjest wywołanie go z wiersza poleceń:

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

Nie próbuj używać time.timelub time.clock(naiwnie) do porównywania prędkości funkcji. Mogą dawać mylące wyniki .

PS. Nie umieszczaj instrukcji print w funkcji, której czas potrzebujesz; w przeciwnym razie zmierzony czas będzie zależeć od prędkości terminala .


65

Fajnie jest to zrobić za pomocą menedżera kontekstu, który automatycznie zapamiętuje czas rozpoczęcia po wejściu do withbloku, a następnie zatrzymuje czas zakończenia po wyjściu z bloku. Przy odrobinie podstępu możesz nawet uzyskać bieżącą licznik czasu, który upłynął w bloku z tej samej funkcji menedżera kontekstu.

Biblioteka podstawowa tego nie ma (ale prawdopodobnie powinna). Po zainstalowaniu możesz wykonywać następujące czynności:

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() )

Oto kod menedżera kontekstu wystarczający do wykonania tej sztuczki:

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

I jakiś działający kod demonstracyjny:

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

Zauważ, że zgodnie z projektem tej funkcji, zwracana wartość elapsed()jest zamrożona przy wyjściu z bloku, a kolejne wywołania zwracają ten sam czas trwania (około 6 sekund w tym przykładzie zabawki).


2
Inny przykład menedżera kontekstu: dabeaz.blogspot.fr/2010/02/…
Jérôme

1
@ Jérôme ładny przykład - zaadaptowałem to jako inną odpowiedź - stackoverflow.com/a/41408510/243392
Brian Burns

62

Czas pomiaru w sekundach:

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

Wyjście :

0:00:01.946339

1
To najbardziej zwięzła odpowiedź z najczystszym wyjściem.
Dave Liu

56

Wolę to. timeitdoc jest zbyt mylące.

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))

Zauważ, że nie ma tu żadnego formatowania, właśnie napisałem hh:mm:ssna wydruku, aby można było zinterpretowaćtime_elapsed


Powiedziano mi, że timeit oblicza czas procesora, czy datetime uwzględnia również wykorzystany czas procesora? Czy to to samo?
Sreehari R

3
Pomiar czasu, który upłynął w ten sposób, jest ryzykowny, ponieważ datetime.now () może przełączać się między tymi dwoma wywołaniami z powodów takich jak synchronizacja czasu w sieci, przełączanie czasu letniego lub skręcanie zegara przez użytkownika.
user1318499

45

Oto inny sposób, aby to zrobić:

>> 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.

Porównywanie w tradycyjny sposób:

>> 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.

Instalacja:

pip install pytictoc

Więcej informacji znajduje się na stronie PyPi .


13
Dobrze byłoby wyjaśnić zalety korzystania z tej biblioteki w porównaniu z innymi podejściami.
hlg

Zagnieżdżona funkcjonalność jest faktycznie zepsuta. Otworzyłem problem opisujący, gdzie jest problem w kodzie, ale repo nie było utrzymywane od roku, więc nie spodziewałbym się zmiany.
PetarMI,

Uważam, że gniazdowanie jest trochę mylące. Gdybym miał napotkać t.tic()zakopany w kodzie, to do mnie, dewelopera, należy zapamiętanie listy miejsc, w których powinienem się tego spodziewać. Czy zdarza ci się zakładać gniazda, czy tylko wiele tictoców?
ScottieB

1
@PetarMI: FYI, właśnie naprawiłem problem z ttictoc. Miałem dość bałaganu, ale teraz powinno być dobrze.
H. Sánchez

32

Oto moje ustalenia po przejściu wielu dobrych odpowiedzi tutaj, a także kilku innych artykułów.

Po pierwsze, jeśli debatujesz między timeiti time.time, timeitma dwie zalety:

  1. timeit wybiera najlepszy czasomierz dostępny w wersji systemu operacyjnego i Pythona.
  2. timeit wyłącza zbieranie śmieci, jednak nie jest to coś, czego możesz chcieć lub nie.

Problem polega na tym, że timeitnie jest tak prosty w użyciu, ponieważ wymaga konfiguracji, a rzeczy stają się brzydkie, gdy masz wiele importów. Idealnie potrzebujesz po prostu dekoratora lub użyj withbloku i zmierz czas. Niestety, nie ma w tym nic wbudowanego, więc masz dwie opcje:

Opcja 1: Użyj biblioteki timebudget

Timebudget jest wszechstronnym i bardzo prosty biblioteki, który można wykorzystać tylko w jednym wierszu kodu po pip zainstalować.

@timebudget  # Record how long this function takes
def my_method():
    # my code

Opcja 2: użyj modułu kodu bezpośrednio

Stworzyłem poniżej mały moduł narzędziowy.

# utils.py
from functools import wraps
import gc
import timeit

def MeasureTime(f, no_print=False, disable_gc=False):
    @wraps(f)
    def _wrapper(*args, **kwargs):
        gcold = gc.isenabled()
        if disable_gc:
            gc.disable()
        start_time = timeit.default_timer()
        try:
            result = f(*args, **kwargs)
        finally:
            elapsed = timeit.default_timer() - start_time
            if disable_gc and gcold:
                gc.enable()
            if not no_print:
                print('"{}": {}s'.format(f.__name__, elapsed))
        return result
    return _wrapper

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print=False, disable_gc=False):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        self.gcold = gc.isenabled()
        if self.disable_gc:
            gc.disable()
        self.start_time = timeit.default_timer()
    def __exit__(self,ty,val,tb):
        self.elapsed = timeit.default_timer() - self.start_time
        if self.disable_gc and self.gcold:
            gc.enable()
        if not self.no_print:
            print('Function "{}": {}s'.format(self.name, self.elapsed))
        return False #re-raise any exceptions

Teraz możesz ustawić czas dowolnej funkcji, umieszczając przed nią dekorator:

import utils

@utils.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

Jeśli chcesz odmierzyć fragment kodu, po prostu włóż go do withbloku:

import utils

#somewhere in my code

with utils.MeasureBlockTime("MyBlock"):
    #do something time consuming
    for i in range(10000):
        print(i)

# rest of my code

Zalety:

Krąży kilka wersji z półprawą, więc chcę wskazać kilka najważniejszych:

  1. Używaj timera od timeit zamiast time.time z powodów opisanych wcześniej.
  2. Możesz wyłączyć GC podczas pomiaru czasu, jeśli chcesz.
  3. Dekorator akceptuje funkcje z nazwanymi lub nienazwanymi parametrami.
  4. Możliwość wyłączenia drukowania w czasie blokowania (użyj, with utils.MeasureBlockTime() as ta następnie t.elapsed).
  5. Możliwość utrzymania włączonej gc dla taktowania bloku.

28

Użycie time.timedo pomiaru wykonania daje ogólny czas wykonania poleceń, w tym czas działania innych procesów na komputerze. Jest to czas, który użytkownik zauważa, ale nie jest to dobre, jeśli chcesz porównać różne fragmenty kodu / algorytmy / funkcje / ...

Więcej informacji na temat timeit:

Jeśli chcesz uzyskać głębszy wgląd w profilowanie:

Aktualizacja : W ciągu ostatniego roku często korzystałem z http://pythonhosted.org/line_profiler/ i uważam, że jest bardzo pomocny i zalecam używanie go zamiast modułu profilu Pythona.


19

Oto mała klasa timera, która zwraca ciąg „hh: mm: ss”:

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

Stosowanie:

# 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

17

Pythonowe moduły cProfile i pstats oferują doskonałą obsługę pomiaru czasu, jaki upłynął w niektórych funkcjach, bez konieczności dodawania kodu do istniejących funkcji.

Na przykład, jeśli masz skrypt Python 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()

Aby uruchomić profiler i wygenerować statystyki dla pliku, wystarczy uruchomić:

python -m cProfile -o timeStats.profile timeFunctions.py

Działa to za pomocą modułu cProfile do profilowania wszystkich funkcji w timeFunctions.py i gromadzenia statystyk w pliku timeStats.profile. Zauważ, że nie musieliśmy dodawać żadnego kodu do istniejącego modułu (timeFunctions.py) i można to zrobić za pomocą dowolnego modułu.

Po utworzeniu pliku statystyk możesz uruchomić moduł pstats w następujący sposób:

python -m pstats timeStats.profile

Spowoduje to uruchomienie interaktywnej przeglądarki statystyk, która zapewnia wiele fajnych funkcji. W konkretnym przypadku użycia możesz po prostu sprawdzić statystyki swojej funkcji. W naszym przykładzie sprawdzenie statystyk dla obu funkcji pokazuje nam:

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)

Przykładowy manekin nie robi wiele, ale daje wyobrażenie o tym, co można zrobić. Najlepsze w tym podejściu jest to, że nie muszę edytować żadnego z moich istniejących kodów, aby uzyskać te liczby i oczywiście pomóc w profilowaniu.


Wszystko w porządku, ale AFAICT nadal mierzy czas procesora, a nie zegar ścienny.
ShreevatsaR

1
W rzeczywistości istnieje pewne zamieszanie; wygląda na to, że cProfile domyślnie patrzy na czas zegara ściennego. Poparłem twoją odpowiedź.
ShreevatsaR

FYI: Jeśli dostaniesz, python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code)sprawdź swoją wersję Pythona, której używasz. Mam to, kiedy pobiegłem python3 -m cProfile...i python -m pstats. Mój błąd, ale dostałem go na sekundę, więc chciałem się podzielić don't forget consistency. =)
JayRizzo

17

Oto inny menedżer kontekstu dla kodu czasu -

Stosowanie:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

lub, jeśli potrzebujesz wartości czasu

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

Na podstawie http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html


17

Użyj modułu profilera. Daje bardzo szczegółowy profil.

import profile
profile.run('main()')

wyprowadza coś takiego:

          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)

Uważam to za bardzo pouczające.


1
Co to jest main()? Przydałby się prosty przykład kodu.
not2qubit

15

Podoba mi się to proste (python 3):

from timeit import timeit

timeit(lambda: print("hello"))

Dane wyjściowe są w mikrosekundach dla pojedynczego wykonania:

2.430883963010274

Objaśnienie : timeit domyślnie wykonuje anonimową funkcję 1 milion razy , a wynik podaje się w sekundach . Dlatego wynik dla jednego pojedynczego wykonania jest taki sam, ale średnio w mikrosekundach .


W przypadku powolnych operacji dodaj mniejszą liczbę iteracji lub możesz czekać wiecznie:

import time

timeit(lambda: time.sleep(1.5), number=1)

Dane wyjściowe są zawsze w sekundach dla całkowitej liczby iteracji:

1.5015795179999714

14

(Tylko w przypadku Ipython) możesz użyć % timeit do zmierzenia średniego czasu przetwarzania:

def foo():
    print "hello"

i wtedy:

%timeit foo()

wynikiem jest coś takiego:

10000 loops, best of 3: 27 µs per loop

4
Warto wspomnieć, że możliwe jest przekazywanie flag do% timeit, na przykład -n określa, ile razy kod powinien zostać powtórzony.
raacer

11

Jeszcze jeden sposób użycia timeit :

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)

10

na python3:

from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)

elegancki i krótki.


co to jest? SM?
KIC

9

Coś w rodzaju super późniejszej odpowiedzi, ale może komuś służy. Jest to sposób na zrobienie tego, co moim zdaniem jest super czyste.

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")

Pamiętaj, że „print” jest funkcją w Pythonie 3, a nie w Pythonie 2.7. Działa jednak z każdą inną funkcją. Twoje zdrowie!


Jak mogę drukować bardzo małe czasy? Dostaję zawsze 0,0 s
Rowland Mtetezi

Możesz to zmienić w dekoratora; dla mnie to wygląda jeszcze lepiej.
Daniel Moskovich,

8

Możesz użyć timeit.

Oto przykład, jak przetestować naive_func, który pobiera parametr za pomocą 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  

Nie potrzebujesz funkcji otoki, jeśli funkcja nie ma żadnych parametrów.


1
lambdaByłoby bardziej zwięźle:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
Ciro Santilli冠状病毒审查六四事件法轮功

7

Możemy również przekształcić czas w czas czytelny dla człowieka.

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')

6

Stworzyłem bibliotekę do tego, jeśli chcesz zmierzyć funkcję, możesz po prostu zrobić to w ten sposób


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


6

Aby uzyskać wgląd w każde wywołanie funkcji rekurencyjnie, wykonaj:

%load_ext snakeviz
%%snakeviz

Po prostu pobiera te 2 linie kodu w notatniku Jupyter i generuje ładny interaktywny diagram. Na przykład:

wprowadź opis zdjęcia tutaj

Oto kod. Ponownie, 2 linie zaczynające się od %są jedynymi dodatkowymi liniami kodu potrzebnymi do użycia snakeviz:

# !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)

Wydaje się również możliwe uruchamianie snakeviz poza notebookami. Więcej informacji na stronie snakeviz .


2
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)

2

To unikalne podejście klasowe oferuje reprezentację drukowalnego ciągu, konfigurowalne zaokrąglanie i wygodny dostęp do upływającego czasu jako ciąg lub zmiennoprzecinkowe. Został opracowany w Pythonie 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)))

Stosowanie:

# 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

1

Zmierz czas wykonania małych fragmentów kodu.

Jednostka czasu : mierzona w sekundach jako liczba zmiennoprzecinkowa

import timeit
t = timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))')
t.timeit()
t.repeat()
>[1.2934070999999676, 1.3335035000000062, 1.422568500000125]

Metoda repeat () jest wygodnym wielokrotnym wywoływaniem timeit () i zwracaniem listy wyników.

repeat(repeat=3

Dzięki tej liście możemy wziąć pod uwagę wszystkie czasy.

Domyślnie timeit () tymczasowo wyłącza zbieranie śmieci w czasie. time.Timer () rozwiązuje ten problem.

Plusy:

timeit.Timer () sprawia, że ​​niezależne czasy są bardziej porównywalne. Gc może być ważnym składnikiem wydajności mierzonej funkcji. Jeśli tak, gc (garbage collector) można ponownie włączyć jako pierwszą instrukcję w ciągu instalacyjnym. Na przykład:

timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))',setup='gc.enable()')

Źródło Python Docs !


1

Jeśli chcesz mieć wygodny czas, możesz użyć prostego dekoratora:

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        original_return_val = func(*args, **kwargs)
        end = time.time()
        print("time elapsed in ", func.__name__, ": ", end - start, sep='')
        return original_return_val

    return wrapper

Możesz go użyć w funkcji, której czas chcesz ustawić w następujący sposób:

@timing_decorator
def function_to_time():
    time.sleep(1)

Następnie za każdym razem, gdy zadzwonisz function_to_time, wydrukuje, ile czasu to zajęło i nazwa funkcji, która jest mierzona.


1

na podstawie rozwiązania kontekstowego menedżera podanego przez https://stackoverflow.com/a/30024601/5095636 , poniżej wersji darmowej lambda, ponieważ flake8 ostrzega przed użyciem lambda zgodnie z E731 :

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start_time = default_timer()

    class _Timer():
      start = start_time
      end = default_timer()
      duration = end - start

    yield _Timer

    end_time = default_timer()
    _Timer.end = end_time
    _Timer.duration = end_time - start_time

test:

from time import sleep

with elapsed_timer() as t:
    print("start:", t.start)
    sleep(1)
    print("end:", t.end)

t.start
t.end
t.duration

1

Oto całkiem udokumentowany iw pełni podpowiedzi dekorator, którego używam jako ogólnego narzędzia:

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

Przykładowe użycie:

from timer import timer


@timer(precision=9)
def takes_long(x: int) -> bool:
    return x in (i for i in range(x + 1))


print(takes_long(10**8))

Wynik:

takes_long: 4.942629056s
True

Dokumenty można sprawdzić za pomocą:

$ python3 -m doctest --verbose -o=ELLIPSIS timer.py

A typ wskazuje na:

$ mypy timer.py

1
To jest super fajne, dziękuję za udostępnienie. Nie spotkałem biblioteki do pisania ani nielokalnego słowa kluczowego - fajnie jest znaleźć nowe rzeczy do nauczenia się. Mam problemy zawijania moja głowa wokół to: Callable[[AnyF], AnyF]. Co to znaczy?
Danny

1
@Danny Na górze mam zdefiniowanego aliasu typu AnyFoznaczać Callable[..., Any], więc AnyFjest funkcją, która może mieć dowolną ilość dowolnych argumentów typu i zwraca niczego. Więc Callable[[AnyF], AnyF]rozwinąłbym się do Callable[[Callable[..., Any]], Callable[..., Any]]. Jest to typ zwracanej wartości timeraka pełnego typu decorator. Jest to funkcja, która przyjmuje jako argument dowolny rodzaj funkcji i zwraca dowolną funkcję.
ruohola

1
Dziękuję za wyjaśnienie! Nadal staram się całkowicie owinąć głowę wokół wnętrz dekoratorów. To bardzo pomogło!
Danny

0

Jedyny sposób, w jaki mogę myśleć, to używanie time.time().

import time
start = time.time()
sleep(5) #just to give it some delay to show it working
finish = time.time()
elapsed = finish - start
print(elapsed)

Mam nadzieję, że to pomoże.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.