Medición del tiempo transcurrido con el módulo de tiempo

337

Con el módulo Time en python, ¿es posible medir el tiempo transcurrido? Si es así, ¿cómo hago eso?

Necesito hacer esto para que si el cursor ha estado en un widget durante un cierto tiempo, ocurra un evento.

rectángulo
fuente
3
NB que cualquier respuesta usando time.time()es incorrecta. El ejemplo más simple es si la hora del sistema cambia durante el período de medición.
OrangeDog
Para su pregunta original con respecto a la activación de un evento si un cursor permanece durante un cierto tiempo en un widget, docs.python.org/3/library/threading.html proporciona todo lo que necesita, creo. El subprocesamiento múltiple y una variable de condición con tiempo de espera podría ser una de las soluciones. Sus circunstancias, sin embargo, actualmente no están claras para responder.
Tora
2
No hay ninguna razón por la que alguien deba usar time.time()para medir el tiempo transcurrido en Python moderno (afectado por cambios manuales, deriva, segundos de salto, etc.). Esta respuesta a continuación debe ser mayor, teniendo en cuenta que esta pregunta es ahora el mejor resultado en Google para medir el tiempo transcurrido.
NPras
También puede medir el tiempo con cProfile profiler: docs.python.org/3/library/profile.html#module-cProfile stackoverflow.com/questions/582336/…
Anton Tarasenko
1
@NPras olvida la "pitón moderna". Siempre fue incorrecto de usar time.time().
OrangeDog

Respuestas:

514
start_time = time.time()
# your code
elapsed_time = time.time() - start_time

También puede escribir un decorador simple para simplificar la medición del tiempo de ejecución de varias funciones:

import time
from functools import wraps

PROF_DATA = {}

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()

        ret = fn(*args, **kwargs)

        elapsed_time = time.time() - start_time

        if fn.__name__ not in PROF_DATA:
            PROF_DATA[fn.__name__] = [0, []]
        PROF_DATA[fn.__name__][0] += 1
        PROF_DATA[fn.__name__][1].append(elapsed_time)

        return ret

    return with_profiling

def print_prof_data():
    for fname, data in PROF_DATA.items():
        max_time = max(data[1])
        avg_time = sum(data[1]) / len(data[1])
        print "Function %s called %d times. " % (fname, data[0]),
        print 'Execution time max: %.3f, average: %.3f' % (max_time, avg_time)

def clear_prof_data():
    global PROF_DATA
    PROF_DATA = {}

Uso:

@profile
def your_function(...):
    ...

Puede perfilar más de una función simultáneamente. Luego, para imprimir medidas, simplemente llame a print_prof_data ():

Vadim Shender
fuente
11
También puede echar un vistazo a profilehooks pip install profilehooks , y su página de inicio aquí
pjama
11
Tenga en cuenta que desde Python 3.3, uno debería usar en time.monotonic()lugar de time.time()medir tiempos de espera o duraciones. docs.python.org/3/library/time.html#time.monotonic
Debilski
39
Vale la pena agregar / señalar aquí que la unidad de medida para el tiempo transcurrido será segundos.
Eric Kramer
44
@EricKramer gracias! gran mascota mía, explicando las medidas sin definir la unidad de medida. Y como un tipo .NET sumergiendo los dedos de los pies en Python por primera vez, automáticamente pensé "milisegundos".
Adam Plocher
2
No funciona si (p. Ej.) Se cambia el reloj del sistema y es posible que no tenga una resolución por segundo. Respuesta correcta: stackoverflow.com/a/47637891/476716
OrangeDog
97

time.time() Hará el trabajo.

import time

start = time.time()
# run your code
end = time.time()

elapsed = end - start

Es posible que desee ver esta pregunta, pero no creo que sea necesario.

lalli
fuente
66
Sí, el tiempo está en segundos
Eric Kramer
Debería cambiar start a start_time.
Zoran Pandovski
time.time()es una mala idea porque el reloj del sistema se puede restablecer, lo que lo hará retroceder en el tiempo. time.monotonic()se encarga de esto (monótono = solo avanza). time.perf_counter()También es monótono pero tiene una precisión aún mayor, por lo que se recomienda para la hora del reloj de pared.
xjcl
76

Para los usuarios que desean un mejor formato,

import time
start_time = time.time()
# your script
elapsed_time = time.time() - start_time
time.strftime("%H:%M:%S", time.gmtime(elapsed_time))

se imprimirá, durante 2 segundos:

'00:00:02'

y durante 7 minutos un segundo:

'00:07:01'

tenga en cuenta que la unidad de tiempo mínima con gmtime es segundos. Si necesita microsegundos, considere lo siguiente:

import datetime
start = datetime.datetime.now()
# some code
end = datetime.datetime.now()
elapsed = end - start
print(elapsed)
# or
print(elapsed.seconds,":",elapsed.microseconds) 

strftime documentación

Rutger Hofste
fuente
1
Gracias por tu respuesta, que me inspira. Voy a usar e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))ese rendimiento casi igual y cubrir la situación que transcurre más de 24 horas.
Tora
@Tora es posible que desee consultar "{}". Format () en lugar de% 02d para futuros problemas de compatibilidad.
Rutger Hofste
2
¡gracias! Ahora me estoy acostumbrando a la nueva. '{: 02d}: {: 02d}: {: 02d}'. Format (e // 3600, (e% 3600 // 60), e% 60)
Tora
puedes usar time.monotonic()como en las otras respuestas?
Endolith
elapsed.secondsserá incorrecto si la duración es mayor a un día. Quieres elapsed.total_seconds()ser resistente
Ash Berlin-Taylor
51

Para la mejor medida del tiempo transcurrido (desde Python 3.3), use time.perf_counter().

Devuelve el valor (en fracciones de segundo) de un contador de rendimiento, es decir, un reloj con la resolución más alta disponible para medir una corta duración. Incluye el tiempo transcurrido durante el sueño y abarca todo el sistema. El punto de referencia del valor devuelto no está definido, de modo que solo la diferencia entre los resultados de llamadas consecutivas es válida.

Para las mediciones del orden de horas / día, que no se preocupan por resolución sub-segundo a fin de utilizar time.monotonic()en su lugar.

Devuelve el valor (en segundos fraccionarios) de un reloj monotónico, es decir, un reloj que no puede retroceder. El reloj no se ve afectado por las actualizaciones del reloj del sistema. El punto de referencia del valor devuelto no está definido, de modo que solo la diferencia entre los resultados de llamadas consecutivas es válida.

En muchas implementaciones, en realidad pueden ser lo mismo.

Antes de 3.3, estás atrapado con time.clock().

En Unix, devuelve el tiempo actual del procesador como un número de coma flotante expresado en segundos. La precisión, y de hecho la definición misma del significado de "tiempo de procesador", depende de la función C del mismo nombre.

En Windows, esta función devuelve los segundos del reloj de pared transcurridos desde la primera llamada a esta función, como un número de punto flotante, basado en la función Win32 QueryPerformanceCounter (). La resolución suele ser mejor que un microsegundo.


Actualización para Python 3.7

Nuevo en Python 3.7 es PEP 564 : agregue nuevas funciones de tiempo con una resolución de nanosegundos.

El uso de estos puede eliminar aún más los errores de redondeo y coma flotante, especialmente si está midiendo períodos muy cortos, o si su aplicación (o máquina con Windows) es de larga duración.

La resolución comienza a romperse perf_counter()después de unos 100 días. Entonces, por ejemplo, después de un año de tiempo de actividad, el intervalo más corto (mayor que 0) que puede medir será mayor que cuando comenzó.


Actualización para Python 3.8

time.clock ahora se ha ido.

OrangeDog
fuente
"En muchas implementaciones, en realidad pueden ser lo mismo". Es cierto que en mi PC Linux Mint, time.monotonic () y time.perf_counter () parecen devolver valores idénticos.
xjcl
7

Por un período más largo.

import time
start_time = time.time()
...
e = int(time.time() - start_time)
print('{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))

imprimiría

00:03:15

si más de 24 horas

25:33:57

Eso está inspirado en la respuesta de Rutger Hofste. Gracias Rutger!

Tora
fuente
6

Debe importar la hora y luego usar el método time.time () para saber la hora actual.

import time

start_time=time.time() #taking current time as starting time

#here your code

elapsed_time=time.time()-start_time #again taking current time - starting time 
Nurul Akter Towhid
fuente
3

Otra buena manera de cronometrar las cosas es usar la estructura con python.

with structure llama automáticamente a los métodos __enter__ y __exit__ , que es exactamente lo que necesitamos para cronometrar las cosas.

Vamos a crear una clase de temporizador .

from time import time

class Timer():
    def __init__(self, message):
        self.message = message
    def __enter__(self):
        self.start = time()
        return None  # could return anything, to be used like this: with Timer("Message") as value:
    def __exit__(self, type, value, traceback):
        elapsed_time = (time() - self.start) * 1000
        print(self.message.format(elapsed_time))

Entonces, uno puede usar la clase Timer así:

with Timer("Elapsed time to compute some prime numbers: {}ms"):
    primes = []
    for x in range(2, 500):
        if not any(x % p == 0 for p in primes):
            primes.append(x)
    print("Primes: {}".format(primes))

El resultado es el siguiente:

Primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89 , 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227 , 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373 , 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499]

Tiempo transcurrido para calcular algunos números primos: 5.01704216003418ms

TM
fuente
2

La respuesta de Vadim Shender es genial. También puede usar un decorador más simple como el siguiente:

import datetime
def calc_timing(original_function):                            
    def new_function(*args,**kwargs):                        
        start = datetime.datetime.now()                     
        x = original_function(*args,**kwargs)                
        elapsed = datetime.datetime.now()                      
        print("Elapsed Time = {0}".format(elapsed-start))     
        return x                                             
    return new_function()  

@calc_timing
def a_func(*variables):
    print("do something big!")
Mohammad
fuente
1

En programación, hay 2 formas principales de medir el tiempo , con diferentes resultados:

>>> print(time.process_time()); time.sleep(10); print(time.process_time())
0.11751394000000001
0.11764988400000001  # took  0 seconds and a bit
>>> print(time.perf_counter()); time.sleep(10); print(time.perf_counter())
3972.465770326
3982.468109075       # took 10 seconds and a bit
  • Tiempo de procesador : es el tiempo que este proceso específico pasa ejecutándose activamente en la CPU. La suspensión, la espera de una solicitud web o el tiempo en que solo se ejecutan otros procesos no contribuirán a esto.

    • Utilizar time.process_time()
  • Tiempo de reloj de pared : se refiere a cuánto tiempo ha pasado "en un reloj colgado en la pared", es decir, fuera del tiempo real.

    • Utilizar time.perf_counter()

      • time.time() también mide el tiempo del reloj de pared, pero se puede restablecer, por lo que puede retroceder en el tiempo
      • time.monotonic() no se puede restablecer (monótono = solo avanza) pero tiene una precisión menor que time.perf_counter()
xjcl
fuente
0

Aquí hay una actualización del código inteligente de Vadim Shender con salida tabular:

import collections
import time
from functools import wraps

PROF_DATA = collections.defaultdict(list)

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()
        ret = fn(*args, **kwargs)
        elapsed_time = time.time() - start_time
        PROF_DATA[fn.__name__].append(elapsed_time)
        return ret
    return with_profiling

Metrics = collections.namedtuple("Metrics", "sum_time num_calls min_time max_time avg_time fname")

def print_profile_data():
    results = []
    for fname, elapsed_times in PROF_DATA.items():
        num_calls = len(elapsed_times)
        min_time = min(elapsed_times)
        max_time = max(elapsed_times)
        sum_time = sum(elapsed_times)
        avg_time = sum_time / num_calls
        metrics = Metrics(sum_time, num_calls, min_time, max_time, avg_time, fname)
        results.append(metrics)
    total_time = sum([m.sum_time for m in results])
    print("\t".join(["Percent", "Sum", "Calls", "Min", "Max", "Mean", "Function"]))
    for m in sorted(results, reverse=True):
        print("%.1f\t%.3f\t%d\t%.3f\t%.3f\t%.3f\t%s" % (100 * m.sum_time / total_time, m.sum_time, m.num_calls, m.min_time, m.max_time, m.avg_time, m.fname))
    print("%.3f Total Time" % total_time)
Steve
fuente