¿Cómo medir el tiempo transcurrido en Python?


1212

Lo que quiero es comenzar a contar el tiempo en algún lugar de mi código y luego obtener el tiempo transcurrido, para medir el tiempo que tardó en ejecutar algunas funciones. Creo que estoy usando mal el módulo timeit, pero los documentos son confusos para mí.

import timeit

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

Respuestas:


1457

Si solo desea medir el tiempo transcurrido del reloj de pared entre dos puntos, puede usar time.time():

import time

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

Esto le da el tiempo de ejecución en segundos.

Otra opción desde 3.3 podría ser usar perf_countero process_time, según sus requisitos. Antes de 3.3 se recomendaba usar time.clock(gracias Amber ). Sin embargo, actualmente está en desuso:

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 coma flotante, basado en la función Win32 QueryPerformanceCounter(). La resolución suele ser mejor que un microsegundo.

En desuso desde la versión 3.3 : el comportamiento de esta función depende de la plataforma: utilice perf_counter()oprocess_time() , en su lugar , según sus requisitos, tenga un comportamiento bien definido.


17
y para microsegundos, use datetime.time ()
Inca

111
(En time.clock()realidad , se prefiere la medición del rendimiento , ya que no se puede interferir si el reloj del sistema se enreda, pero en .time()su mayoría cumple el mismo propósito.)
Ámbar

44
Creo que python -mtimeit es mucho mejor ya que se ejecuta más veces y está construido como una forma nativa de medir el tiempo en python
Visgean Skeloru

44
¿Hay una buena manera de convertir el tiempo de ejecución resultante en segundos a algo así como HH: MM :: SS?
Danijel

12
@Danijel: print(timedelta(seconds=execution_time)). Aunque es una pregunta aparte.
jfs

689

Usar en timeit.default_timerlugar de timeit.timeit. El primero proporciona el mejor reloj disponible en su plataforma y versión de Python automáticamente:

from timeit import default_timer as timer

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

timeit.default_timer se asigna a time.time () o time.clock () según el sistema operativo. En Python 3.3+ default_timer es time.perf_counter () en todas las plataformas. Ver Python - time.clock () vs. time.time () - precision?

Ver también:


29
Excelente respuesta - usando timeit producirá resultados mucho más precisos, ya que automáticamente dará cuenta de cosas como la recolección de basura y OS diferencias
lkgarrison

1
Esto da tiempo en ms o segundos?
Katie

3
@KhushbooTiwari en fracciones de segundo.
jfs

55
Creo que esta nota de la documentación oficial debe agregarsedefault_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: La medición del rendimiento es muy difícil de una manera sutil (es fácil engañarse a sí mismo). Hay muchos otros comentarios que podrían ser relevantes aquí. Sigue los enlaces en la respuesta. Es posible que también le interese el perfmódulo (inexistente en el momento de la respuesta) que proporciona la misma interfaz, pero a veces difiere de las timeitdecisiones del módulo sobre cómo medir el rendimiento del tiempo.
jfs

129

Python 3 solamente:

Como time.clock () está en desuso a partir de Python 3.3 , querrá usarlo time.perf_counter()para la sincronización de todo el sistema, o time.process_time()para la sincronización de todo el proceso, tal como solía usar time.clock():

import time

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

La nueva función process_timeno incluirá el tiempo transcurrido durante el sueño.


28
Usar entimeit.default_timer lugar de time.perf_counter. El primero elegirá el temporizador apropiado para medir el rendimiento del tiempo ajustado para su plataforma y versión de Python. process_time()hace no incluye el tiempo durante el sueño y por lo tanto no es apropiado para medir el tiempo transcurrido.
jfs

2
Estoy usando la implementación sugerida por Pierre, ¿se dan los valores en segundos?
ugotchi

Esta respuesta parece fuera de tema (bueno, la pregunta no era muy específica). Hay dos medidas de "tiempo": tiempo de reloj de pared entre dos puntos, del consumo de CPU del proceso.
Franklin Piat

87

Dada una función que le gustaría cronometrar,

test.py:

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

la forma más fácil de usar timeites llamarlo desde la línea de comandos:

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

No intente usar time.timeo time.clock(ingenuamente) para comparar la velocidad de las funciones. Pueden dar resultados engañosos .

PD. No ponga declaraciones impresas en una función que desee cronometrar; de lo contrario, el tiempo medido dependerá de la velocidad del terminal .


65

Es divertido hacer esto con un administrador de contexto que recuerda automáticamente la hora de inicio al ingresar a un withbloque, luego congela la hora de finalización al salir del bloque. Con un pequeño truco, incluso puede obtener una cuenta del tiempo transcurrido dentro del bloque desde la misma función de administrador de contexto.

La biblioteca principal no tiene esto (pero probablemente debería). Una vez en su lugar, puede hacer cosas como:

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

Aqui esta un código de administrador contexto suficiente para hacer el truco:

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

Y un código de demostración ejecutable:

import time

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

Tenga en cuenta que mediante el diseño de esta función, el valor de retorno de elapsed()se congela al salir del bloque, y las llamadas adicionales devuelven la misma duración (de aproximadamente 6 segundos en este ejemplo de juguete).


2
Otro ejemplo de gestor de contexto: dabeaz.blogspot.fr/2010/02/…
Jérôme

1
@ Jérôme buen ejemplo - Lo adapté como otra respuesta - stackoverflow.com/a/41408510/243392
Brian Burns

62

Tiempo de medición en segundos:

from timeit import default_timer as timer
from datetime import timedelta

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

Salida :

0:00:01.946339

1
Esta es la respuesta más concisa con la salida más limpia.
Dave Liu

56

Prefiero esto. timeitdoc es demasiado confuso.

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

Tenga en cuenta que no hay ningún formato aquí, simplemente escribí hh:mm:ssen la copia impresa para que uno pueda interpretartime_elapsed


Me dijeron que timeit calcula el tiempo de CPU, ¿datetime también tiene en cuenta el tiempo de CPU utilizado? Son estos la misma cosa?
Sreehari R

3
Es arriesgado medir el tiempo transcurrido de esta manera porque datetime.now () puede cambiar entre las dos llamadas por razones como la sincronización de la hora de la red, el cambio de horario de verano o el usuario girando el reloj.
user1318499

45

Aquí hay otra forma de hacer esto:

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

Comparando con la forma tradicional:

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

Instalación:

pip install pytictoc

Consulte la página de PyPi para más detalles.


13
Sería bueno explicar la ventaja de usar esta biblioteca sobre otros enfoques.
hlg

La funcionalidad anidada está realmente rota. Abrí un problema que describe dónde está el problema en el código, pero el repositorio no se ha mantenido en un año, por lo que no esperaría un cambio.
PetarMI

La anidación me parece un poco confusa. Si me encontrara t.tic()enterrado en el código, depende del desarrollador mantener una lista mental de en qué parte de la serie debería esperar que esto sea. ¿Te encuentras configurando nidos o simplemente múltiples tictocs?
ScottieB

1
@PetarMI: FYI, acabo de solucionar el problema con ttictoc. Tenía un desastre, pero ahora debería estar bien.
H. Sánchez

33

Aquí están mis hallazgos después de pasar por muchas buenas respuestas aquí, así como algunos otros artículos.

Primero, si está debatiendo entre timeity time.time, timeittiene dos ventajas:

  1. timeit selecciona el mejor temporizador disponible en su sistema operativo y la versión de Python.
  2. timeit deshabilita la recolección de basura, sin embargo, esto no es algo que puede desear o no.

Ahora el problema es que timeitno es tan fácil de usar porque necesita configuración y las cosas se ponen feas cuando tienes un montón de importaciones. Idealmente, solo quieres un decorador o usarwith bloquear y medir el tiempo. Desafortunadamente, no hay nada incorporado disponible para esto, por lo que tiene dos opciones:

Opción 1: usar la biblioteca timebudget

El timebudget es una biblioteca versátil y muy simple que se puede utilizar sólo en una línea de código después de pepita instalar.

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

Opción 2: usar el módulo de código directamente

Creé a continuación un pequeño módulo de utilidad.

# 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

Ahora puede cronometrar cualquier función simplemente colocando un decorador frente a ella:

import utils

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

Si desea cronometrar la parte del código, simplemente póngalo dentro del withbloque:

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

Ventajas:

Hay varias versiones con respaldo medio flotando, así que quiero señalar algunos aspectos destacados:

  1. Use el temporizador de timeit en lugar de time.time por las razones descritas anteriormente.
  2. Puede deshabilitar GC durante el tiempo si lo desea.
  3. Decorator acepta funciones con parámetros con o sin nombre.
  4. Posibilidad de desactivar la impresión en tiempo de bloque (uso with utils.MeasureBlockTime() as ty luego t.elapsed).
  5. Capacidad para mantener gc habilitado para el tiempo de bloqueo.

28

El uso time.timepara medir la ejecución le brinda el tiempo de ejecución general de sus comandos, incluido el tiempo de ejecución empleado por otros procesos en su computadora. Es el momento en que el usuario se da cuenta, pero no es bueno si desea comparar diferentes fragmentos de código / algoritmos / funciones / ...

Más información sobre timeit:

Si desea una visión más profunda de la creación de perfiles:

Actualización : Utilicé mucho http://pythonhosted.org/line_profiler/ durante el último año y me resulta muy útil y recomiendo usarlo en lugar del módulo de perfil Pythons.


19

Aquí hay una pequeña clase de temporizador que devuelve la cadena "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

Uso:

# 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

Los módulos python cProfile y pstats ofrecen un gran soporte para medir el tiempo transcurrido en ciertas funciones sin tener que agregar ningún código alrededor de las funciones existentes.

Por ejemplo, si tiene un script 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()

Para ejecutar el generador de perfiles y generar estadísticas para el archivo, simplemente puede ejecutar:

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

Lo que está haciendo es usar el módulo cProfile para perfilar todas las funciones en timeFunctions.py y recopilar las estadísticas en el archivo timeStats.profile. Tenga en cuenta que no tuvimos que agregar ningún código al módulo existente (timeFunctions.py) y esto se puede hacer con cualquier módulo.

Una vez que tenga el archivo de estadísticas, puede ejecutar el módulo pstats de la siguiente manera:

python -m pstats timeStats.profile

Esto ejecuta el navegador de estadísticas interactivas que le brinda una gran cantidad de funcionalidades. Para su caso de uso particular, puede verificar las estadísticas de su función. En nuestro ejemplo, la comprobación de estadísticas para ambas funciones nos muestra lo siguiente:

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)

El ejemplo ficticio no hace mucho, pero le da una idea de lo que se puede hacer. La mejor parte de este enfoque es que no tengo que editar ninguno de mis códigos existentes para obtener estos números y obviamente ayudar con la creación de perfiles.


Todo esto está bien, pero AFAICT aún mide el tiempo de CPU, no el tiempo del reloj de pared.
ShreevatsaR

1
En realidad hay algo de confusión; parece que cProfile mira la hora del reloj de pared por defecto. He votado tu respuesta.
ShreevatsaR

FYI: Si consigues python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code)verificar tu versión de Python que estás ejecutando. Obtuve esto cuando corrí python3 -m cProfile...y python -m pstats. Mi error me atrapó por un segundo, así que quería compartir don't forget consistency. =)
JayRizzo

17

Aquí hay otro administrador de contexto para el código de tiempo:

Uso:

from benchmark import benchmark

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

o, si necesita el valor del tiempo

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

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


17

Utilice el módulo perfilador. Da un perfil muy detallado.

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

produce algo como:

          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)

Lo he encontrado muy informativo.


1
¿Qué es main()? Sería más útil si pudiera proporcionar un ejemplo de código simple.
not2qubit

15

Me gusta simple (python 3):

from timeit import timeit

timeit(lambda: print("hello"))

La salida es microsegundos para una sola ejecución:

2.430883963010274

Explicación : timeit ejecuta la función anónima 1 millón de veces por defecto y el resultado se da en segundos . Por lo tanto, el resultado para 1 ejecución individual es la misma cantidad pero en microsegundos en promedio.


Para operaciones lentas , agregue un número menor de iteraciones o podría estar esperando para siempre:

import time

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

La salida siempre está en segundos para el número total de iteraciones:

1.5015795179999714

14

(Solo con Ipython) puede usar % timeit para medir el tiempo de procesamiento promedio:

def foo():
    print "hello"

y entonces:

%timeit foo()

el resultado es algo como:

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

44
Vale la pena mencionar que es posible pasar banderas a% timeit, por ejemplo -n especifica cuántas veces se debe repetir el código.
Raacer

11

Una forma más de usar timeit :

from timeit import timeit

def func():
    return 1 + 1

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

10

en python3:

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

Elegante y corto.


¿Que es esto? ¿em?
KIC

@KIC Está en segundos.
Guimoute hace

9

Una especie de respuesta súper posterior, pero tal vez tenga un propósito para alguien. Esta es una forma de hacerlo que creo que es super limpia.

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

Tenga en cuenta que "imprimir" es una función en Python 3 y no en Python 2.7. Sin embargo, funciona con cualquier otra función. ¡Salud!


¿Cómo puedo imprimir tiempos muy pequeños? Siempre estoy obteniendo 0.0 segundos
Rowland Mtetezi

Puedes convertir esto en un decorador; Esto se ve aún mejor para mí.
Daniel Moskovich

8

Puedes usar timeit.

Aquí hay un ejemplo sobre cómo probar naive_func que toma parámetros usando 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  

No necesita la función de contenedor si la función no tiene ningún parámetro.


1
A lambdasería más sucinto:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

7

También podemos convertir el tiempo en tiempo legible por humanos.

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

Hice una biblioteca para esto, si quieres medir una función puedes hacerlo así


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

Para obtener información sobre todas las llamadas a funciones de forma recursiva, haga lo siguiente:

%load_ext snakeviz
%%snakeviz

Solo toma esas 2 líneas de código en un cuaderno Jupyter , y genera un bonito diagrama interactivo. Por ejemplo:

ingrese la descripción de la imagen aquí

Aquí está el código. Una vez más, las 2 líneas que comienzan con %son las únicas líneas de código adicionales necesarias para usar 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)

También parece posible ejecutar snakeviz fuera de los portátiles. Más información en el sitio web de 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

Este enfoque único basado en clases ofrece una representación de cadena imprimible, redondeo personalizable y un acceso conveniente al tiempo transcurrido como una cadena o un flotador. Fue desarrollado con Python 3.7.

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.com/a/57931660/

    def __init__(self, round_ndigits: int = 0):
        self._round_ndigits = round_ndigits
        self._start_time = timeit.default_timer()

    def __call__(self) -> float:
        return timeit.default_timer() - self._start_time

    def __str__(self) -> str:
        return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))

Uso:

# 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

Mida el tiempo de ejecución de pequeños fragmentos de código.

Unidad de tiempo : medida en segundos como flotador

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]

El método repeat () es conveniente para llamar a timeit () varias veces y devolver una lista de resultados.

repeat(repeat=3

Con esta lista podemos tomar una media de todos los tiempos.

Por defecto, timeit () desactiva temporalmente la recolección de basura durante el tiempo. time.Timer () resuelve este problema.

Pros:

timeit.Timer () hace que los tiempos independientes sean más comparables. El gc puede ser un componente importante del desempeño de la función que se está midiendo. Si es así, gc (recolector de basura) se puede volver a habilitar como la primera instrucción en la cadena de configuración. Por ejemplo:

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

Fuente Python Docs !


1

Si desea poder cronometrar funciones convenientemente, puede usar un decorador simple:

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

Puede usarlo en una función que desee cronometrar así:

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

Luego, cada vez que llame function_to_time, imprimirá cuánto tiempo tomó y el nombre de la función que se está cronometrando.


1

basado en la solución de administrador de contexto dada por https://stackoverflow.com/a/30024601/5095636 , a continuación la versión gratuita lambda, ya que flake8 advierte sobre el uso de lambda según 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

prueba:

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

La forma más fácil de calcular la duración de una operación:

import time

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

<operations, programs>

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

1

Aquí hay un decorador bastante bien documentado y completamente insinuado que utilizo como utilidad general:

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

Ejemplo de uso:

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

Salida:

takes_long: 4.942629056s
True

Los doctest se pueden consultar con:

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

Y el tipo sugiere:

$ mypy timer.py

1
Esto es genial, gracias por compartir. No he encontrado la biblioteca de escritura o la palabra clave no local, es divertido encontrar cosas nuevas para aprender. Tengo problemas para envolver mi cabeza alrededor de esto: Callable[[AnyF], AnyF]. Qué significa eso?
Danny

1
@Danny En la parte superior, he definido el alias de tipo AnyFpara que signifique Callable[..., Any], por lo que AnyFes una función que puede tomar cualquier cantidad de argumentos de tipo y devolver cualquier cosa. Entonces Callable[[AnyF], AnyF]se expandiría a Callable[[Callable[..., Any]], Callable[..., Any]]. Este es el tipo del valor de retorno de timeraka el tipo completo de decorator. Es una función que toma cualquier tipo de función como único argumento y devuelve cualquier tipo de función.
Ruohola

1
¡Gracias por la explicación! Todavía estoy tratando de entender completamente el interior de los decoradores. ¡Esto ayudó mucho!
Danny
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.