Wenn Sie wirklich das direkte Äquivalent wollen, rufen Sie einfach an tic = time.time()und toc = time.time()dann, print toc-tic, 'sec Elapsed'wie die Leute unten gesagt haben, timeitist es jedoch robuster.
Joe Kington
Ich scheine bessere Ergebnisse zu erzielen, wenn ich den Ansatz von @ JoeKington in Verbindung mit timeit.default_timer () verwende, wie zum Beispiel : tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer(), dann print toc-tic.
littleO
1
Die Bibliothek pytictoc scheint am konvektivsten zu sein, die Syntax ist sogar etwas ordentlicher als die unten stehende ttictoc. pypi.org/project/pytictoc
FlorianH
Antworten:
171
Abgesehen von dem, timeitwas ThiefMaster erwähnt hat, ist eine einfache Möglichkeit, dies zu tun, nur (nach dem Importieren time):
t = time.time()# do stuff
elapsed = time.time()- t
@eat: Ich bin respektvoll anderer Meinung. Die Leute haben den Unix- timeBefehl verwendet, um die Laufzeit von Programmen für immer zu messen, und diese Methode repliziert dies in Python-Code. Ich sehe nichts falsch daran, solange es das richtige Werkzeug für den Job ist. timeitist nicht immer so, und ein Profiler ist eine viel schwerere Lösung für die meisten Anforderungen
Eli Bendersky
4
Für die letzte Zeile würde ich vorschlagen print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'. Ohne% .2f ist es schwer zu verstehen. Danke für die tolle Idee.
Kann Kavaklıoğlu
4
Dies sieht auf den ersten Blick sehr praktisch aus, erfordert jedoch in der Praxis das Einrücken des gewünschten Codeblocks, was je nach Länge des Codeblocks und dem Editor Ihrer Wahl recht unpraktisch sein kann. Immer noch eine elegante Lösung, die sich bei verschachtelter Verwendung korrekt verhält.
Stefan
1
Ich denke du willst elapsed = t - time.time()statt elapsed = time.time() - t. In letzterem ist verstrichen negativ. Ich habe diese Änderung als Bearbeitung vorgeschlagen.
Rysqui
3
@rysqui - Ist die aktuelle Zeit nicht immer eine größere Zahl als die vorherige ? Ich würde denken, dass dies elapsed = time.time() - tdie Form ist, die immer einen positiven Wert ergibt.
Scott Smith
31
Ich hatte die gleiche Frage, als ich von Matlab nach Python migrierte. Mit Hilfe dieses Threads konnte ich ein genaues Analogon des Matlab tic()und seiner toc()Funktionen erstellen . Fügen Sie einfach den folgenden Code oben in Ihr Skript ein.
import timedefTicTocGenerator():# Generator that returns time differences
ti =0# initial time
tf = time.time()# final timewhileTrue:
ti = tf
tf = time.time()yield tf-ti # returns the time differenceTicToc=TicTocGenerator()# create an instance of the TicTocGen generator# This will be the main function through which we define both tic() and toc()def toc(tempBool=True):# Prints the time difference yielded by generator instance TicToc
tempTimeInterval =next(TicToc)if tempBool:print("Elapsed time: %f seconds.\n"%tempTimeInterval )def tic():# Records a time in TicToc, marks the beginning of a time interval
toc(False)
Das ist es! Jetzt sind wir voll einsatzbereit tic()und toc()genau wie in Matlab. Beispielsweise
Tatsächlich ist dies vielseitiger als die integrierten Matlab-Funktionen. Hier können Sie eine weitere Instanz von erstellen TicTocGenerator, um mehrere Vorgänge zu verfolgen oder um die Dinge anders zu planen. Während wir beispielsweise ein Skript zeitlich festlegen, können wir jetzt jedes Teil des Skripts sowie das gesamte Skript separat zeitlich festlegen. (Ich werde ein konkretes Beispiel geben)
TicToc2=TicTocGenerator()# create another instance of the TicTocGen generatordef toc2(tempBool=True):# Prints the time difference yielded by generator instance TicToc2
tempTimeInterval =next(TicToc2)if tempBool:print("Elapsed time 2: %f seconds.\n"%tempTimeInterval )def tic2():# Records a time in TicToc2, marks the beginning of a time interval
toc2(False)
Jetzt sollten Sie in der Lage sein, zwei verschiedene Dinge zeitlich zu steuern: Im folgenden Beispiel werden das gesamte Skript und Teile eines Skripts separat zeitlich festgelegt.
Eigentlich müssen Sie nicht einmal tic()jedes Mal verwenden. Wenn Sie eine Reihe von Befehlen haben, die Sie zeitlich festlegen möchten, können Sie schreiben
Das absolut beste Analogon von Tic und Toc wäre, sie einfach in Python zu definieren.
def tic():#Homemade version of matlab tic and toc functionsimport timeglobal startTime_for_tictoc
startTime_for_tictoc = time.time()def toc():import timeif'startTime_for_tictoc'in globals():print"Elapsed time is "+ str(time.time()- startTime_for_tictoc)+" seconds."else:print"Toc: start time not set"
Dies verhält sich bei verschachtelter Verwendung von ticund toc, die Matlab unterstützt, nicht korrekt . Ein wenig mehr Raffinesse wäre erforderlich.
Stefan
2
Ich habe ähnliche Funktionen in meinem eigenen Code implementiert, als ich ein grundlegendes Timing benötigte. Ich würde jedoch die import timeAußenseite beider Funktionen entfernen , da dies möglicherweise einige Zeit dauern kann.
Bas Swinckels
Wenn Sie darauf bestehen, diese Technik zu verwenden, und Sie sie benötigen, um verschachtelte Tics / Tocs zu verarbeiten, erstellen Sie die globale Liste und lassen Sie sie darauf ticdrücken und tocaus ihr herausspringen .
Ahmed Fasih
1
Ich habe auch an anderer Stelle gelesen, dass dies timeit.default_timer()besser ist als time.time()weil time.clock()es je nach Betriebssystem besser geeignet sein könnte
Miguel
@AhmedFasih Das ist, was meine Antwort tut, obwohl mehr Dinge verbessert werden könnten.
Antonimmo
15
Normalerweise IPython die %time, %timeit, %prunund %lprun(wenn man hat line_profilerinstalliert) erfüllt meine Profilierungs Bedürfnisse ganz gut. Ein Anwendungsfall für tic-tocähnliche Funktionen ergab sich jedoch, als ich versuchte, Berechnungen zu profilieren, die interaktiv gesteuert wurden, dh durch die Mausbewegung des Benutzers in einer GUI. Ich hatte das Gefühl, tics und tocs in den Quellen zu spammen, während interaktives Testen der schnellste Weg wäre, um die Engpässe aufzudecken. Ich habe mich für Eli Benderskys Kurs entschieden Timer, war aber nicht ganz glücklich, da ich die Einrückung meines Codes ändern musste, was in einigen Editoren unpraktisch sein kann und das Versionskontrollsystem verwirrt. Darüber hinaus besteht möglicherweise die Notwendigkeit, die Zeit zwischen Punkten in verschiedenen Funktionen zu messen, was mit dem nicht funktionieren würdewithAussage. Nachdem ich viel Python-Cleverness ausprobiert habe, ist hier die einfache Lösung, die meiner Meinung nach am besten funktioniert hat:
from time import time
_tstart_stack =[]def tic():
_tstart_stack.append(time())def toc(fmt="Elapsed: %s s"):print fmt %(time()- _tstart_stack.pop())
Da dies funktioniert, indem die Startzeiten auf einem Stapel verschoben werden, funktioniert es für mehrere Ebenen von tics und tocs korrekt . Es erlaubt auch, die Formatzeichenfolge der tocAnweisung zu ändern , um zusätzliche Informationen anzuzeigen, die mir an Elis TimerKlasse gefallen haben .
Aus irgendeinem Grund habe ich mich mit dem Overhead einer reinen Python-Implementierung befasst und deshalb auch ein C-Erweiterungsmodul getestet:
Dies ist für MacOSX, und ich habe Code weggelassen, um zu überprüfen, ob lvler der Kürze halber außerhalb der Grenzen liegt. Während sich tictoc.res()auf meinem System eine Auflösung von etwa 50 Nanosekunden ergibt, stellte ich fest, dass der Jitter beim Messen einer Python-Anweisung leicht im Mikrosekundenbereich liegt (und viel mehr, wenn er von IPython verwendet wird). Zu diesem Zeitpunkt wird der Overhead der Python-Implementierung vernachlässigbar, sodass sie mit der gleichen Sicherheit wie die C-Implementierung verwendet werden kann.
Ich fand heraus, dass die Nützlichkeit des tic-tocAnsatzes praktisch auf Codeblöcke beschränkt ist, deren Ausführung mehr als 10 Mikrosekunden dauert. Darunter sind Mittelungsstrategien wie in timeiterforderlich, um eine genaue Messung zu erhalten.
Ich habe gerade ein Modul [tictoc.py] erstellt, um verschachtelte Tic-Token zu erreichen, was Matlab auch tut.
from time import time
tics =[]def tic():
tics.append(time())def toc():if len(tics)==0:returnNoneelse:return time()-tics.pop()
Und so funktioniert es:
from tictoc import tic, toc# This keeps track of the whole process
tic()# Timing a small portion of code (maybe a loop)
tic()# -- Nested code here --# End
toc()# This returns the elapse time (in seconds) since the last invocation of tic()
toc()# This does the same for the first tic()
Ich muss Sie warnen, dass sich dies möglicherweise nicht wie gewünscht verhält, wenn es von mehr als einem Modul gleichzeitig verwendet wird, da sich (AFAIK) -Module wie Singletons verhalten.
Antonimmo
3
Schauen Sie sich das timeitModul an. Es ist nicht wirklich gleichwertig, aber wenn sich der Code, den Sie zeitlich festlegen möchten, in einer Funktion befindet, können Sie ihn problemlos verwenden.
Dies kann auch mit einem Wrapper erfolgen. Sehr allgemeine Art, Zeit zu halten.
Der Wrapper in diesem Beispielcode umschließt jede Funktion und gibt die Zeit aus, die zum Ausführen der Funktion benötigt wird:
def timethis(f):import time
def wrapped(*args,**kwargs):
start = time.time()
r = f(*args,**kwargs)print"Executing {0} took {1} seconds".format(f.func_name, time.time()-start)return r
return wrapped
@timethisdef thistakestime():for x in range(10000000):pass
thistakestime()
Die Wrapper-Funktion timethis wird als Dekorateur bezeichnet. Eine etwas ausführlichere Erklärung hier: medium.com/pythonhive/…
Mircea
1
Ich habe die Antwort von @Eli Bendersky ein wenig geändert, um ctor __init__()und dtor __del__()für das Timing zu verwenden, damit es bequemer verwendet werden kann, ohne den ursprünglichen Code einzurücken:
Ein Problem bei dieser Implementierung ist die Tatsache, dass timersie nach dem letzten Aufruf nicht gelöscht wird, wenn nach der forSchleife ein anderer Code folgt . Um den letzten Timer-Wert zu erhalten, sollte der timerAfter-the- forLoop gelöscht oder überschrieben werden , z timer = None. B. via .
Bastelflp
1
@bastelflp Ich habe gerade festgestellt, dass ich falsch verstanden habe, was Sie meinten ... Ihr Vorschlag wurde jetzt in den Code aufgenommen. Vielen Dank.
Genau wie bei Eli kann es als Kontextmanager verwendet werden:
import time
withTimer('Count'):for i in range(0,10_000_000):pass
Ausgabe:
[Count]Elapsed:0.27 seconds
Ich habe es auch aktualisiert, um die gemeldeten Zeiteinheiten (Sekunden) zu drucken und die Anzahl der Stellen zu verringern, wie von Can vorgeschlagen, und mit der Option, auch an eine Protokolldatei anzuhängen. Sie müssen datetime importieren, um die Protokollierungsfunktion verwenden zu können:
import time
import datetime
withTimer('Count','log.txt'):for i in range(0,10_000_000):pass
in einem utils.pyModul, und ich benutze es mit einem
from utils importTictoc
tic, toc =Tictoc()
Diesen Weg
Sie können einfach verwenden tic(), toc()und nisten sie mögen in Matlab
Alternativ können Sie sie benennen : tic(1), toc(1)oder tic('very-important-block'), toc('very-important-block')und Timer mit unterschiedlichen Namen stören nicht
Durch den Import auf diese Weise werden Interferenzen zwischen den verwendeten Modulen verhindert.
(Hier druckt toc die verstrichene Zeit nicht aus, sondern gibt sie zurück.)
tic = time.time()
undtoc = time.time()
dann,print toc-tic, 'sec Elapsed'
wie die Leute unten gesagt haben,timeit
ist es jedoch robuster.tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
, dannprint toc-tic
.Antworten:
Abgesehen von dem,
timeit
was ThiefMaster erwähnt hat, ist eine einfache Möglichkeit, dies zu tun, nur (nach dem Importierentime
):Ich habe eine Hilfsklasse, die ich gerne benutze:
Es kann als Kontextmanager verwendet werden:
Manchmal finde ich diese Technik bequemer als
timeit
- alles hängt davon ab, was Sie messen möchten.quelle
time
Befehl verwendet, um die Laufzeit von Programmen für immer zu messen, und diese Methode repliziert dies in Python-Code. Ich sehe nichts falsch daran, solange es das richtige Werkzeug für den Job ist.timeit
ist nicht immer so, und ein Profiler ist eine viel schwerere Lösung für die meisten Anforderungenprint 'Elapsed: %.2f seconds % (time.time() - self.tstart)'
. Ohne% .2f ist es schwer zu verstehen. Danke für die tolle Idee.elapsed = t - time.time()
stattelapsed = time.time() - t
. In letzterem ist verstrichen negativ. Ich habe diese Änderung als Bearbeitung vorgeschlagen.elapsed = time.time() - t
die Form ist, die immer einen positiven Wert ergibt.Ich hatte die gleiche Frage, als ich von Matlab nach Python migrierte. Mit Hilfe dieses Threads konnte ich ein genaues Analogon des Matlab
tic()
und seinertoc()
Funktionen erstellen . Fügen Sie einfach den folgenden Code oben in Ihr Skript ein.Das ist es! Jetzt sind wir voll einsatzbereit
tic()
undtoc()
genau wie in Matlab. BeispielsweiseTatsächlich ist dies vielseitiger als die integrierten Matlab-Funktionen. Hier können Sie eine weitere Instanz von erstellen
TicTocGenerator
, um mehrere Vorgänge zu verfolgen oder um die Dinge anders zu planen. Während wir beispielsweise ein Skript zeitlich festlegen, können wir jetzt jedes Teil des Skripts sowie das gesamte Skript separat zeitlich festlegen. (Ich werde ein konkretes Beispiel geben)Jetzt sollten Sie in der Lage sein, zwei verschiedene Dinge zeitlich zu steuern: Im folgenden Beispiel werden das gesamte Skript und Teile eines Skripts separat zeitlich festgelegt.
Eigentlich müssen Sie nicht einmal
tic()
jedes Mal verwenden. Wenn Sie eine Reihe von Befehlen haben, die Sie zeitlich festlegen möchten, können Sie schreibenIch hoffe das ist hilfreich.
quelle
Das absolut beste Analogon von Tic und Toc wäre, sie einfach in Python zu definieren.
Dann können Sie sie verwenden als:
quelle
tic
undtoc
, die Matlab unterstützt, nicht korrekt . Ein wenig mehr Raffinesse wäre erforderlich.import time
Außenseite beider Funktionen entfernen , da dies möglicherweise einige Zeit dauern kann.tic
drücken undtoc
aus ihr herausspringen .timeit.default_timer()
besser ist alstime.time()
weiltime.clock()
es je nach Betriebssystem besser geeignet sein könnteNormalerweise IPython die
%time
,%timeit
,%prun
und%lprun
(wenn man hatline_profiler
installiert) erfüllt meine Profilierungs Bedürfnisse ganz gut. Ein Anwendungsfall fürtic-toc
ähnliche Funktionen ergab sich jedoch, als ich versuchte, Berechnungen zu profilieren, die interaktiv gesteuert wurden, dh durch die Mausbewegung des Benutzers in einer GUI. Ich hatte das Gefühl,tic
s undtoc
s in den Quellen zu spammen, während interaktives Testen der schnellste Weg wäre, um die Engpässe aufzudecken. Ich habe mich für Eli Benderskys Kurs entschiedenTimer
, war aber nicht ganz glücklich, da ich die Einrückung meines Codes ändern musste, was in einigen Editoren unpraktisch sein kann und das Versionskontrollsystem verwirrt. Darüber hinaus besteht möglicherweise die Notwendigkeit, die Zeit zwischen Punkten in verschiedenen Funktionen zu messen, was mit dem nicht funktionieren würdewith
Aussage. Nachdem ich viel Python-Cleverness ausprobiert habe, ist hier die einfache Lösung, die meiner Meinung nach am besten funktioniert hat:Da dies funktioniert, indem die Startzeiten auf einem Stapel verschoben werden, funktioniert es für mehrere Ebenen von
tic
s undtoc
s korrekt . Es erlaubt auch, die Formatzeichenfolge dertoc
Anweisung zu ändern , um zusätzliche Informationen anzuzeigen, die mir an ElisTimer
Klasse gefallen haben .Aus irgendeinem Grund habe ich mich mit dem Overhead einer reinen Python-Implementierung befasst und deshalb auch ein C-Erweiterungsmodul getestet:
Dies ist für MacOSX, und ich habe Code weggelassen, um zu überprüfen, ob
lvl
er der Kürze halber außerhalb der Grenzen liegt. Während sichtictoc.res()
auf meinem System eine Auflösung von etwa 50 Nanosekunden ergibt, stellte ich fest, dass der Jitter beim Messen einer Python-Anweisung leicht im Mikrosekundenbereich liegt (und viel mehr, wenn er von IPython verwendet wird). Zu diesem Zeitpunkt wird der Overhead der Python-Implementierung vernachlässigbar, sodass sie mit der gleichen Sicherheit wie die C-Implementierung verwendet werden kann.Ich fand heraus, dass die Nützlichkeit des
tic-toc
Ansatzes praktisch auf Codeblöcke beschränkt ist, deren Ausführung mehr als 10 Mikrosekunden dauert. Darunter sind Mittelungsstrategien wie intimeit
erforderlich, um eine genaue Messung zu erhalten.quelle
Sie können
tic
undtoc
von verwendenttictoc
. Installieren Sie es mitUnd importieren Sie sie einfach wie folgt in Ihr Skript
quelle
Ich habe gerade ein Modul [tictoc.py] erstellt, um verschachtelte Tic-Token zu erreichen, was Matlab auch tut.
Und so funktioniert es:
Ich hoffe, es hilft.
quelle
Schauen Sie sich das
timeit
Modul an. Es ist nicht wirklich gleichwertig, aber wenn sich der Code, den Sie zeitlich festlegen möchten, in einer Funktion befindet, können Sie ihn problemlos verwenden.quelle
timeit
am besten für Benchmarks. Es muss nicht einmal eine einzelne Funktion sein, Sie können unglaublich komplexe Anweisungen übergeben.Im Code:
Haftungsausschluss: Ich bin der Autor dieser Bibliothek.
quelle
Dies kann auch mit einem Wrapper erfolgen. Sehr allgemeine Art, Zeit zu halten.
Der Wrapper in diesem Beispielcode umschließt jede Funktion und gibt die Zeit aus, die zum Ausführen der Funktion benötigt wird:
quelle
Ich habe die Antwort von @Eli Bendersky ein wenig geändert, um ctor
__init__()
und dtor__del__()
für das Timing zu verwenden, damit es bequemer verwendet werden kann, ohne den ursprünglichen Code einzurücken:Setzen Sie den Timer ("blahblah") einfach an den Anfang eines lokalen Bereichs. Die verstrichene Zeit wird am Ende des Bereichs gedruckt:
Es druckt aus:
quelle
timer
sie nach dem letzten Aufruf nicht gelöscht wird, wenn nach derfor
Schleife ein anderer Code folgt . Um den letzten Timer-Wert zu erhalten, sollte dertimer
After-the-for
Loop gelöscht oder überschrieben werden , ztimer = None
. B. via .Aktualisierung von Elis Antwort auf Python 3:
Genau wie bei Eli kann es als Kontextmanager verwendet werden:
Ausgabe:
Ich habe es auch aktualisiert, um die gemeldeten Zeiteinheiten (Sekunden) zu drucken und die Anzahl der Stellen zu verringern, wie von Can vorgeschlagen, und mit der Option, auch an eine Protokolldatei anzuhängen. Sie müssen datetime importieren, um die Protokollierungsfunktion verwenden zu können:
quelle
Aufbauend auf den Antworten von Stefan und Antonimmo habe ich am Ende gesetzt
in einem
utils.py
Modul, und ich benutze es mit einemDiesen Weg
tic()
,toc()
und nisten sie mögen in Matlabtic(1)
,toc(1)
odertic('very-important-block')
,toc('very-important-block')
und Timer mit unterschiedlichen Namen stören nicht(Hier druckt toc die verstrichene Zeit nicht aus, sondern gibt sie zurück.)
quelle