Wie kann man die verstrichene Zeit in Python messen?


1208

Was ich möchte, ist, irgendwo in meinem Code mit dem Zählen der Zeit zu beginnen und dann die verstrichene Zeit abzurufen, um die Zeit zu messen, die zum Ausführen weniger Funktionen benötigt wurde. Ich denke, ich verwende das Timeit-Modul falsch, aber die Dokumente sind für mich nur verwirrend.

import timeit

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

Antworten:


1454

Wenn Sie nur die verstrichene Wanduhrzeit zwischen zwei Punkten messen möchten, können Sie Folgendes verwenden time.time():

import time

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

Dies gibt die Ausführungszeit in Sekunden an.

Eine weitere Option seit 3.3 ist möglicherweise die Verwendung von perf_counteroder process_time, abhängig von Ihren Anforderungen. Vor 3.3 wurde die Verwendung empfohlen time.clock(danke Amber ). Derzeit ist es jedoch veraltet:

Geben Sie unter Unix die aktuelle Prozessorzeit als Gleitkommazahl in Sekunden zurück. Die Genauigkeit und tatsächlich die Definition der Bedeutung von „Prozessorzeit“ hängt von der der gleichnamigen C-Funktion ab.

Unter Windows gibt diese Funktion die seit dem ersten Aufruf dieser Funktion verstrichenen Wanduhrsekunden als Gleitkommazahl zurück, basierend auf der Win32-Funktion QueryPerformanceCounter(). Die Auflösung ist normalerweise besser als eine Mikrosekunde.

Veraltet seit Version 3.3 : Das Verhalten dieser Funktion hängt von der Plattform ab: Verwenden Sie stattdessen perf_counter()oderprocess_time() , abhängig von Ihren Anforderungen, ein genau definiertes Verhalten.


17
und für Mikrosekunden verwenden Sie datetime.time ()
Inca

110
(Für die Leistungsmessung time.clock()wird eigentlich bevorzugt, da es nicht gestört werden kann, wenn die Systemuhr durcheinander gerät, aber .time()meistens den gleichen Zweck erfüllt.)
Amber

4
Ich denke, dass Python -mtimeit viel besser ist, da es öfter ausgeführt wird und als native Methode zum Messen der Zeit in Python erstellt wird
Visgean Skeloru

4
Gibt es eine gute Möglichkeit, die resultierende Exekturationszeit in Sekunden in etwas wie HH: MM :: SS umzuwandeln?
Danijel

12
@Danijel : print(timedelta(seconds=execution_time)). Obwohl es eine separate Frage ist.
JFS

688

Verwenden Sie timeit.default_timeranstelle von timeit.timeit. Ersteres bietet automatisch die beste auf Ihrer Plattform und Version von Python verfügbare Uhr:

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

timeit.default_timer wird je nach Betriebssystem time.time () oder time.clock () zugewiesen. Auf Python 3.3+ DEFAULT_TIMER ist time.perf_counter () auf allen Plattformen. Siehe Python - time.clock () vs. time.time () - Genauigkeit?

Siehe auch:


28
Ausgezeichnete Antwort - die Verwendung von timeit führt zu weitaus genaueren Ergebnissen, da automatisch Dinge wie
Speicherbereinigung

1
Dies gibt Zeit in ms oder Sekunden?
Katie

3
@ KhushbooTiwari in Sekundenbruchteilen.
JFS

5
Ich denke, dieser Hinweis aus der offiziellen Dokumentation muss hinzugefügt werdendefault_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: Die Leistungsmessung ist auf subtile Weise sehr schwierig (es ist leicht, sich selbst in die Irre zu führen). Es gibt viele andere Bemerkungen, die hier relevant sein könnten. Folgen Sie den Links in der Antwort. Möglicherweise interessieren Sie sich auch für das perfModul (das zum Zeitpunkt der Antwort nicht vorhanden ist) , das dieselbe Schnittstelle bietet, das sich jedoch manchmal von den timeitModulentscheidungen zur Messung der Zeitleistung unterscheidet.
JFS

129

Nur Python 3:

Da time.clock () ab Python 3.3 veraltet ist , sollten Sie das time.perf_counter()systemweite Timing oder das prozessweite time.process_time()Timing genau so verwenden, wie Sie es früher verwendet haben time.clock():

import time

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

Die neue Funktion process_timeberücksichtigt nicht die im Schlaf verstrichene Zeit.


28
Verwenden Sietimeit.default_timer anstelle von time.perf_counter. Ersterer wählt den geeigneten Timer aus, um die für Ihre Plattform und Python-Version eingestellte Zeitleistung zu messen. process_time()tut nicht enthalten die Zeit während des Schlafes und daher ist es nicht angemessen verstrichene Zeit zu messen.
JFS

2
Ich verwende die von Pierre vorgeschlagene Implementierung. Werden die Werte in Sekunden angegeben?
Ugotchi

Diese Antwort scheint nicht zum Thema zu gehören (die Frage war nicht sehr spezifisch). Es gibt zwei "Zeit" -Messungen: die Wanduhrzeit zwischen zwei Punkten des CPU-Verbrauchs des Prozesses.
Franklin Piat

87

Wenn Sie eine Funktion haben, die Sie zeitlich festlegen möchten,

test.py:

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

Am einfachsten timeitist es, es über die Befehlszeile aufzurufen:

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

Versuchen Sie nicht, die Geschwindigkeit von Funktionen zu verwenden time.timeoder time.clock(naiv) zu vergleichen. Sie können zu irreführenden Ergebnissen führen .

PS. Fügen Sie keine print-Anweisungen in eine Funktion ein, die Sie zeitlich festlegen möchten. Andernfalls hängt die gemessene Zeit von der Geschwindigkeit des Terminals ab .


65

Es macht Spaß, dies mit einem Kontextmanager zu tun, der sich beim Start eines withBlocks automatisch die Startzeit merkt und beim Beenden des Blocks die Endzeit einfriert. Mit ein wenig Trick können Sie mit derselben Kontextmanager-Funktion sogar eine Liste der abgelaufenen verstrichenen Zeit innerhalb des Blocks abrufen.

Die Kernbibliothek hat dies nicht (sollte es aber wahrscheinlich). Sobald Sie an Ort und Stelle sind, können Sie Dinge tun wie:

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 ist der Kontextmanager- Code, der ausreicht, um den Trick auszuführen :

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

Und ein lauffähiger Demo-Code:

import time

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

Beachten Sie, dass aufgrund dieser Funktion der Rückgabewert von elapsed()beim Blockausgang eingefroren wird und weitere Aufrufe dieselbe Dauer zurückgeben (in diesem Spielzeugbeispiel etwa 6 Sekunden).


2
Anderes Beispiel für einen Kontextmanager
Jérôme

1
@ Jérôme schönes Beispiel - Ich habe es als eine andere Antwort angepasst - stackoverflow.com/a/41408510/243392
Brian Burns

62

Messzeit in Sekunden:

from timeit import default_timer as timer
from datetime import timedelta

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

Ausgabe :

0:00:01.946339

1
Dies ist die präziseste Antwort mit der saubersten Ausgabe.
Dave Liu

56

Ich bevorzuge das. timeitdoc ist viel zu verwirrend.

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

Beachten Sie, dass hier keine Formatierung stattfindet. Ich habe nur hh:mm:ssin den Ausdruck geschrieben, damit man sie interpretieren kanntime_elapsed


Mir wurde gesagt, dass timeit die CPU-Zeit berechnet. Berücksichtigt datetime auch die verwendete CPU-Zeit? Sind das die gleichen?
Sreehari R

3
Es ist riskant, die verstrichene Zeit auf diese Weise zu messen, da datetime.now () zwischen den beiden Aufrufen aus Gründen wie der Synchronisierung der Netzwerkzeit, der Sommerzeitumschaltung oder dem Drehen der Uhr durch den Benutzer wechseln kann.
user1318499

45

Hier ist eine andere Möglichkeit, dies zu tun:

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

Vergleich mit traditioneller Art:

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

Installation:

pip install pytictoc

Weitere Informationen finden Sie auf der PyPi-Seite .


13
Es wäre gut, den Vorteil der Verwendung dieser Bibliothek gegenüber anderen Ansätzen zu erklären.
hlg

Die verschachtelte Funktionalität ist tatsächlich defekt. Ich habe ein Problem geöffnet, das beschreibt, wo das Problem im Code liegt, aber das Repo wurde seit einem Jahr nicht mehr gewartet, sodass ich keine Änderung erwarten würde.
PetarMI

Ich finde die Verschachtelung etwas verwirrend. Wenn ich t.tic()im Code vergraben rüberkomme, liegt es an mir, dass der Entwickler eine mentale Liste darüber führt, wo in der Serie ich dies erwarten sollte. Bauen Sie Nester oder nur mehrere Tictocs auf?
ScottieB

1
@PetarMI: Zu Ihrer Information, ich habe gerade das Problem mit behoben ttictoc. Ich hatte ein ziemliches Durcheinander, aber es sollte jetzt gut sein.
H. Sánchez

33

Hier sind meine Ergebnisse, nachdem ich hier viele gute Antworten sowie einige andere Artikel durchgesehen habe.

Erstens, wenn Sie zwischen timeitund diskutieren time.time, timeithat das zwei Vorteile:

  1. timeit Wählt den besten verfügbaren Timer für Ihr Betriebssystem und Ihre Python-Version aus.
  2. timeit Deaktiviert die Speicherbereinigung. Dies ist jedoch nicht das, was Sie möglicherweise möchten oder nicht möchten.

Das Problem ist nun, dass timeites nicht so einfach zu bedienen ist, da es eingerichtet werden muss und die Dinge hässlich werden, wenn Sie eine Reihe von Importen haben. Idealerweise möchten Sie nur einen Dekorateur oder verwenden withBlock und messen die Zeit. Leider ist hierfür nichts eingebaut, sodass Sie zwei Möglichkeiten haben:

Option 1: Verwenden Sie die Timebudget-Bibliothek

Das Zeitbudget ist eine vielseitige und sehr einfache Bibliothek, die Sie nach der Pip-Installation nur in einer Codezeile verwenden können.

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

Option 2: Verwenden Sie das Codemodul direkt

Ich habe unten ein kleines Utility-Modul erstellt.

# 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

Jetzt können Sie jede Funktion zeitlich festlegen, indem Sie einen Dekorateur davor stellen:

import utils

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

Wenn Sie einen Teil des Codes zeitlich festlegen möchten, fügen Sie ihn einfach in den withBlock ein:

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

Vorteile:

Es gibt mehrere Versionen mit halber Rückseite, daher möchte ich auf einige Highlights hinweisen:

  1. Verwenden Sie aus den zuvor beschriebenen Gründen den Timer von timeit anstelle von time.time.
  2. Sie können GC während des Timings deaktivieren, wenn Sie möchten.
  3. Decorator akzeptiert Funktionen mit benannten oder unbenannten Parametern.
  4. Möglichkeit, das Drucken im Block-Timing zu deaktivieren (verwenden with utils.MeasureBlockTime() as tund dann t.elapsed).
  5. Möglichkeit, gc für das Block-Timing aktiviert zu halten.

28

Wenn time.timeSie die Ausführung messen, erhalten Sie die Gesamtausführungszeit Ihrer Befehle, einschließlich der Laufzeit, die andere Prozesse auf Ihrem Computer verbringen. Es ist die Zeit, die der Benutzer bemerkt, aber es ist nicht gut, wenn Sie verschiedene Codefragmente / Algorithmen / Funktionen / ... vergleichen möchten.

Weitere Informationen zu timeit:

Wenn Sie einen tieferen Einblick in die Profilerstellung erhalten möchten:

Update : Ich habe http://pythonhosted.org/line_profiler/ im letzten Jahr häufig verwendet und finde es sehr hilfreich und empfehle, es anstelle des Pythons-Profilmoduls zu verwenden.


19

Hier ist eine winzige Timer-Klasse, die den String "hh: mm: ss" zurückgibt:

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

Verwendungszweck:

# 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

Die Python-Module cProfile und pstats bieten eine hervorragende Unterstützung für die Messung der in bestimmten Funktionen verstrichenen Zeit, ohne dass Code um die vorhandenen Funktionen hinzugefügt werden muss.

Zum Beispiel, wenn Sie ein Python-Skript timeFunctions.py haben:

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

Um den Profiler auszuführen und Statistiken für die Datei zu generieren, können Sie einfach Folgendes ausführen:

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

Dazu wird das cProfile-Modul verwendet, um alle Funktionen in timeFunctions.py zu profilieren und die Statistiken in der Datei timeStats.profile zu sammeln. Beachten Sie, dass wir dem vorhandenen Modul (timeFunctions.py) keinen Code hinzufügen mussten und dies mit jedem Modul möglich ist.

Sobald Sie die Statistikdatei haben, können Sie das pstats-Modul wie folgt ausführen:

python -m pstats timeStats.profile

Dadurch wird der interaktive Statistikbrowser ausgeführt, der Ihnen viele nützliche Funktionen bietet. Für Ihren speziellen Anwendungsfall können Sie einfach die Statistiken für Ihre Funktion überprüfen. In unserem Beispiel zeigt die Überprüfung der Statistiken für beide Funktionen Folgendes:

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)

Das Dummy-Beispiel macht nicht viel, gibt Ihnen aber eine Vorstellung davon, was getan werden kann. Das Beste an diesem Ansatz ist, dass ich keinen meiner vorhandenen Codes bearbeiten muss, um diese Zahlen zu erhalten und offensichtlich bei der Profilerstellung zu helfen.


All dies ist in Ordnung, aber AFAICT misst immer noch die CPU-Zeit, nicht die Wanduhrzeit.
ShreevatsaR

1
Eigentlich gibt es einige Verwirrung; Es scheint, dass cProfile standardmäßig die Wanduhrzeit anzeigt. Ich habe Ihre Antwort positiv bewertet.
ShreevatsaR

Zu python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code)Ihrer Information: Wenn Sie Ihre Python-Version überprüfen, die Sie ausführen. Ich habe das bekommen, als ich rannte python3 -m cProfile...und python -m pstats. Mein Fehler hat mich aber für eine Sekunde erwischt, also wollte ich teilen don't forget consistency. =)
JayRizzo

17

Hier ist ein weiterer Kontextmanager für Timing-Code:

Verwendungszweck:

from benchmark import benchmark

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

oder, wenn Sie den Zeitwert benötigen

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

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


17

Verwenden Sie das Profiler-Modul. Es gibt ein sehr detailliertes Profil.

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

es gibt so etwas aus wie:

          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)

Ich fand es sehr informativ.


1
Was ist main()? Wäre nützlicher, wenn Sie ein einfaches Codebeispiel bereitstellen könnten.
not2qubit

15

Ich mag es einfach (Python 3):

from timeit import timeit

timeit(lambda: print("hello"))

Die Ausgabe erfolgt in Mikrosekunden für eine einzelne Ausführung:

2.430883963010274

Erläuterung : timeit führt die anonyme Funktion standardmäßig 1 Million Mal aus und das Ergebnis wird in Sekunden angegeben . Daher ist das Ergebnis für eine einzelne Ausführung der gleiche Betrag, jedoch im Durchschnitt in Mikrosekunden .


Fügen Sie bei langsamen Vorgängen eine geringere Anzahl von Iterationen hinzu, oder Sie könnten ewig warten:

import time

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

Die Ausgabe erfolgt immer in Sekunden für die Gesamtzahl der Iterationen:

1.5015795179999714

14

(Nur mit Ipython) Sie können % timeit verwenden , um die durchschnittliche Verarbeitungszeit zu messen:

def foo():
    print "hello"

und dann:

%timeit foo()

Das Ergebnis ist so etwas wie:

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

4
Erwähnenswert ist, dass Flags an% timeit übergeben werden können. Beispiel: -n gibt an, wie oft der Code wiederholt werden soll.
Raacer

11

Eine weitere Möglichkeit, timeit zu verwenden :

from timeit import timeit

def func():
    return 1 + 1

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

10

auf python3:

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

elegant und kurz.


Was ist das? Frau?
KIC

9

Eine Art super spätere Antwort, aber vielleicht erfüllt sie einen Zweck für jemanden. Dies ist ein Weg, den ich für super sauber halte.

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

Beachten Sie, dass "print" eine Funktion in Python 3 und nicht in Python 2.7 ist. Es funktioniert jedoch mit jeder anderen Funktion. Prost!


Wie kann ich sehr kleine Zeiten drucken? Ich bekomme irgendwie immer 0.0sec
Rowland Mtetezi

Sie können dies in einen Dekorateur verwandeln; das sieht für mich noch besser aus.
Daniel Moskovich

8

Sie können timeit verwenden.

Hier ist ein Beispiel zum Testen von naive_func, das Parameter mit Python REPL verwendet:

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

Sie benötigen keine Wrapper-Funktion, wenn die Funktion keine Parameter hat.


1
A lambdawäre prägnanter:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
Ciro Santilli 法轮功 病毒 审查. 事件 4

7

Wir können Zeit auch in lesbare Zeit umwandeln.

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

Ich habe dafür eine Bibliothek erstellt. Wenn Sie eine Funktion messen möchten, können Sie dies einfach so tun


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

Gehen Sie folgendermaßen vor, um einen Einblick in alle Funktionsaufrufe zu erhalten:

%load_ext snakeviz
%%snakeviz

Es werden nur diese 2 Codezeilen in einem Jupyter-Notizbuch benötigt , und es wird ein schönes interaktives Diagramm erstellt. Zum Beispiel:

Geben Sie hier die Bildbeschreibung ein

Hier ist der Code. Auch hier sind die 2 Zeilen, die mit beginnen, %die einzigen zusätzlichen Codezeilen, die für die Verwendung von snakeviz benötigt werden:

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

Es scheint auch möglich zu sein, snakeviz außerhalb von Notebooks auszuführen. Weitere Infos auf der Snakeviz-Website .


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

Dieser einzigartige klassenbasierte Ansatz bietet eine druckbare Zeichenfolgendarstellung, eine anpassbare Rundung und einen bequemen Zugriff auf die verstrichene Zeit als Zeichenfolge oder Float. Es wurde mit Python 3.7 entwickelt.

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

Verwendungszweck:

# 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

Messen Sie die Ausführungszeit kleiner Codefragmente.

Zeiteinheit : gemessen in Sekunden als Schwimmer

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]

Mit der Methode repeat () können Sie timeit () mehrmals aufrufen und eine Ergebnisliste zurückgeben.

repeat(repeat=3

Mit dieser Liste können wir einen Mittelwert aller Zeiten ziehen.

Standardmäßig deaktiviert timeit () die Speicherbereinigung während des Timings vorübergehend. time.Timer () löst dieses Problem.

Vorteile:

timeit.Timer () macht unabhängige Timings vergleichbarer. Der Gleichstrom kann ein wichtiger Bestandteil der Leistung der gemessenen Funktion sein. In diesem Fall kann gc (Garbage Collector) als erste Anweisung in der Setup-Zeichenfolge wieder aktiviert werden. Zum Beispiel:

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

Quell- Python-Dokumente !


1

Wenn Sie Funktionen bequem zeitlich festlegen möchten, können Sie einen einfachen Dekorateur verwenden:

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

Sie können es für eine Funktion verwenden, die Sie wie folgt zeitlich festlegen möchten:

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

Bei jedem Aufruf function_to_timewird dann gedruckt, wie lange es gedauert hat und wie die Funktion zeitgesteuert ist.


1

basierend auf der Kontextmanager-Lösung von https://stackoverflow.com/a/30024601/5095636 , unter der Lambda-freien Version, warnt flake8 vor der Verwendung von Lambda gemäß 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

Prüfung:

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

Der einfachste Weg, um die Dauer einer Operation zu berechnen:

import time

start_time = time.time()
print(time.ctime())

<operations, programs>

print('minutes: ',(time.time() - start_time)/60)

1

Hier ist ein ziemlich gut dokumentierter und vollständig typisierter Dekorateur, den ich als allgemeines Dienstprogramm verwende:

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

Anwendungsbeispiel:

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

Ausgabe:

takes_long: 4.942629056s
True

Die Doktrinen können überprüft werden mit:

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

Und der Typ gibt Hinweise mit:

$ mypy timer.py

1
Das ist super cool, danke fürs Teilen. Ich habe weder die Schreibbibliothek noch das nichtlokale Schlüsselwort gefunden - es macht Spaß, neue Dinge zu finden, über die ich lernen kann. Ich habe Probleme, meinen Kopf darum zu wickeln : Callable[[AnyF], AnyF]. Was bedeutet das?
Danny vor

1
@Danny Auf der oberen ich den Typ Alias definiert haben AnyFverstanden Callable[..., Any], so AnyFist eine Funktion , die jede Menge jeglicher Art Argumente und Rückkehr etwas dauern kann. So Callable[[AnyF], AnyF]würde erweitern Callable[[Callable[..., Any]], Callable[..., Any]]. Dies ist der Typ des Rückgabewerts von timeraka the full type of decorator. Es ist eine Funktion, die jede Art von Funktion als einziges Argument verwendet und jede Art von Funktion zurückgibt.
Ruohola vor

1
Danke für die Erklärung! Ich versuche immer noch, meinen Kopf vollständig um die Einbauten der Dekorateure zu wickeln. Das hat sehr geholfen!
Danny
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.