¿Cuál es la mejor manera de ejecutar repetidamente una función cada x segundos?


284

Quiero ejecutar repetidamente una función en Python cada 60 segundos para siempre (al igual que un NSTimer en el Objetivo C). Este código se ejecutará como un demonio y es efectivamente como llamar al script de Python cada minuto usando un cron, pero sin requerir que el usuario lo configure.

En esta pregunta sobre un cron implementado en Python , la solución parece efectivamente dormir () durante x segundos. No necesito una funcionalidad tan avanzada, así que tal vez algo como esto funcione

while True:
    # Code executed here
    time.sleep(60)

¿Hay algún problema previsible con este código?


84
Un punto pedante, pero puede ser crítico, su código anterior no se ejecuta cada 60 segundos, deja un espacio de 60 segundos entre ejecuciones. Solo ocurre cada 60 segundos si el código ejecutado no demora en absoluto.
Simon

44
También time.sleep(60)puede regresar tanto antes como después
jfs

55
Todavía me pregunto: ¿hay algún problema previsible con este código?
Banana

1
El "problema previsible" es que no puede esperar 60 iteraciones por hora con solo usar time.sleep (60). Entonces, si agrega un elemento por iteración y mantiene una lista de longitud establecida ... el promedio de esa lista no representará un "período" de tiempo consistente; por lo tanto, funciones como "promedio móvil" pueden hacer referencia a puntos de datos que son demasiado antiguos, lo que distorsionará su indicación.
litepresence

2
@Banana Sí, puede esperar cualquier problema causado porque su script no se ejecuta EXACTAMENTE cada 60 segundos. Por ejemplo. Comencé a hacer algo como esto para dividir las transmisiones de video y subirlas, y terminé recibiendo strems de 5 a 10 segundos más porque la cola de medios se almacena en búfer mientras proceso los datos dentro del bucle. Depende de tus datos. Si la función es algún tipo de perro guardián simple que le advierte, por ejemplo, cuando su disco está lleno, no debería tener ningún problema con esto. Si está revisando las alertas de advertencia de una planta de energía nuclear, puede terminar en una ciudad completamente explotado x
DGoiko

Respuestas:


229

Si el programa no tiene un bucle de eventos ya, utilice el sched módulo, que implementa un planificador de eventos de propósito general.

import sched, time
s = sched.scheduler(time.time, time.sleep)
def do_something(sc): 
    print("Doing stuff...")
    # do your stuff
    s.enter(60, 1, do_something, (sc,))

s.enter(60, 1, do_something, (s,))
s.run()

Si ya está utilizando una biblioteca de bucles evento como asyncio, trio, tkinter, PyQt5, gobject, kivy, y muchos otros - sólo programar la tarea utilizando los métodos de su biblioteca bucle de eventos existente, en vez.


16
El módulo programado es para que las funciones de programación se ejecuten después de un tiempo, ¿cómo se usa para repetir una llamada de función cada x segundos sin usar time.sleep ()?
Baishampayan Ghose

2
@Baishampayan: solo programe una nueva carrera.
nosklo

3
Entonces apscheduler en packages.python.org/APScheduler también debería recibir una mención en este punto.
Daniel F

66
nota: esta versión puede derivar. Podrías usar enterabs()para evitarlo. Aquí hay una versión sin deriva para comparar .
jfs

8
@JavaSa: porque "haz tus cosas" no es instantáneo y los errores time.sleeppueden acumularse aquí. "ejecutar cada X segundos" y "ejecutar con un retraso de ~ X segundos repetidamente" no son lo mismo. Ver también este comentario
jfs el

180

Bloquee su ciclo de tiempo en el reloj del sistema de esta manera:

import time
starttime = time.time()
while True:
    print "tick"
    time.sleep(60.0 - ((time.time() - starttime) % 60.0))

22
+1. la suya y la twistedrespuesta son las únicas respuestas que ejecutan una función cada xsegundo. El resto ejecuta la función con un retraso de xsegundos después de cada llamada.
jfs

13
Si agrega un código a esto que tardó más de un segundo ... Se agotaría el tiempo de espera y comenzaría a retrasarse ... La respuesta aceptada en este caso es correcta ... Cualquiera puede repetir un comando de impresión simple y que se ejecute cada segundo sin demora ...
Enojado 84

55
Prefiero from time import time, sleepdebido a las implicaciones existenciales;)
Será

14
Funciona fantásticamente. No hay necesidad de restarle starttimesi comienza sincronizándolo en un momento determinado: time.sleep(60 - time.time() % 60)ha funcionado bien para mí. Lo he usado como time.sleep(1200 - time.time() % 1200)y me da registros en el :00 :20 :40, exactamente como quería.
TemporalWolf

2
@AntonSchigur para evitar la deriva después de múltiples iteraciones. Una iteración individuo puede comenzar poco antes o después dependiendo de sleep(), timer()la precisión y el tiempo que se tarda en ejecutar el cuerpo del bucle, pero en promedio iteraciones siempre se producen en los límites de intervalo (aunque algunos se saltan): while keep_doing_it(): sleep(interval - timer() % interval). Compárelo con solo while keep_doing_it(): sleep(interval)dónde se pueden acumular errores después de varias iteraciones.
jfs

72

Es posible que desee considerar Twisted, que es una biblioteca de red de Python que implementa el patrón Reactor .

from twisted.internet import task, reactor

timeout = 60.0 # Sixty seconds

def doWork():
    #do work here
    pass

l = task.LoopingCall(doWork)
l.start(timeout) # call every sixty seconds

reactor.run()

Mientras que "while True: sleep (60)" probablemente funcionará, Twisted probablemente ya implemente muchas de las características que eventualmente necesitará (demonización, registro o manejo de excepciones como lo señala bobince) y probablemente será una solución más sólida


Gran respuesta también, muy precisa sin deriva. Me pregunto si esto también pone la CPU en suspensión mientras espera para ejecutar la tarea (es decir, no está ocupado esperando).
smoothware

1
esto se desplaza al nivel de milisegundos
Derek Eden

1
¿Qué significa "derivas en el nivel de milisegundos"?
Jean-Paul Calderone

¿Hay alguna forma de romper el ciclo, digamos después de 10 minutos? @Aaron Maenpaa
Alper

67

Si desea una forma sin bloqueo para ejecutar su función periódicamente, en lugar de un bucle infinito de bloqueo, usaría un temporizador roscado. De esta manera, su código puede seguir ejecutándose y realizar otras tareas y aún así llamar su función cada n segundos. Utilizo mucho esta técnica para imprimir información de progreso en tareas largas intensivas de CPU / Disco / Red.

Aquí está el código que publiqué en una pregunta similar, con control start () y stop ():

from threading import Timer

class RepeatedTimer(object):
    def __init__(self, interval, function, *args, **kwargs):
        self._timer     = None
        self.interval   = interval
        self.function   = function
        self.args       = args
        self.kwargs     = kwargs
        self.is_running = False
        self.start()

    def _run(self):
        self.is_running = False
        self.start()
        self.function(*self.args, **self.kwargs)

    def start(self):
        if not self.is_running:
            self._timer = Timer(self.interval, self._run)
            self._timer.start()
            self.is_running = True

    def stop(self):
        self._timer.cancel()
        self.is_running = False

Uso:

from time import sleep

def hello(name):
    print "Hello %s!" % name

print "starting..."
rt = RepeatedTimer(1, hello, "World") # it auto-starts, no need of rt.start()
try:
    sleep(5) # your long-running job goes here...
finally:
    rt.stop() # better in a try/finally block to make sure the program ends!

caracteristicas:

  • Biblioteca estándar solamente, sin dependencias externas
  • start()y stop()es seguro llamar varias veces incluso si el temporizador ya se ha iniciado / detenido
  • la función a llamar puede tener argumentos posicionales y nombrados
  • Puede cambiar en intervalcualquier momento, será efectivo después de la próxima ejecución. Lo mismo para args, kwargse incluso function!

Esta solución parece derivar con el tiempo; Necesitaba una versión que apuntara a llamar a la función cada n segundos sin deriva. Publicaré una actualización en una pregunta separada.
eraoul

En def _run(self)que estoy tratando de envolver mi cabeza alrededor de eso que llama self.start()antes self.function(). ¿Puedes elaborar? Pensaría que llamar start()primero self.is_runningsiempre sería Falseasí, luego siempre giraríamos un nuevo hilo.
Rich Episcopo

1
Creo que llegué al fondo. La solución de @ MestreLion ejecuta una función cada xsegundo (es decir, t = 0, t = 1x, t = 2x, t = 3x, ...) donde en el póster original, el código de muestra ejecuta una función con un intervalo de x segundos entre ellos. Además, creo que esta solución tiene un error si intervales más corta que el tiempo que lleva functionejecutar. En ese caso, self._timerse sobrescribirá en la startfunción.
Rich Episcopo

Sí, @RichieEpiscopo, la llamada a .function()after .start()es ejecutar la función en t = 0. Y no creo que sea un problema si functionlleva más tiempo interval, pero sí, podría haber algunas condiciones de carrera en el código.
MestreLion

Esta es la única forma sin bloqueo que podría obtener. Gracias.
barra invertidaN

35

La forma más fácil que creo que es:

import time

def executeSomething():
    #code here
    time.sleep(60)

while True:
    executeSomething()

De esta manera, su código se ejecuta, luego espera 60 segundos y luego se ejecuta nuevamente, espera, ejecuta, etc. No es necesario complicar las cosas: D


La palabra clave True debería estar en mayúscula
Sean Cain

39
En realidad, esta no es la respuesta: time sleep () solo se puede usar para esperar X segundos después de cada ejecución. Por ejemplo, si su función tarda 0,5 segundos en ejecutarse y usa time.sleep (1), significa que su función se ejecuta cada 1,5 segundos, no 1. Debe usar otros módulos y / o subprocesos para asegurarse de que algo funcione durante Y veces en cada X segundo.
kommradHomer

1
@kommradHomer: respuesta de Dave Rove demuestra que se puede utilizar time.sleep()ejecutar algo cada X segundos
JFS

2
En mi opinión, el código debería llamar time.sleep()en while Truebucle como:def executeSomething(): print('10 sec left') ; while True: executeSomething(); time.sleep(10)
Leonard Lepadatu

22
import time, traceback

def every(delay, task):
  next_time = time.time() + delay
  while True:
    time.sleep(max(0, next_time - time.time()))
    try:
      task()
    except Exception:
      traceback.print_exc()
      # in production code you might want to have this instead of course:
      # logger.exception("Problem while executing repetitive task.")
    # skip tasks if we are behind schedule:
    next_time += (time.time() - next_time) // delay * delay + delay

def foo():
  print("foo", time.time())

every(5, foo)

Si desea hacer esto sin bloquear el código restante, puede usar esto para permitir que se ejecute en su propio hilo:

import threading
threading.Thread(target=lambda: every(5, foo)).start()

Esta solución combina varias características que rara vez se encuentran combinadas en las otras soluciones:

  • Manejo de excepciones: medida de lo posible en este nivel, las excepciones se manejan adecuadamente, es decir, se registran con fines de depuración sin abortar nuestro programa.
  • Sin encadenamiento: la implementación común en forma de cadena (para programar el próximo evento) que encuentra en muchas respuestas es frágil en el aspecto de que si algo sale mal dentro del mecanismo de programación ( threading.Timero lo que sea), esto terminará la cadena. Entonces no ocurrirán más ejecuciones, incluso si el motivo del problema ya está solucionado. Un bucle simple y esperando con un simplesleep() es mucho más robusto en comparación.
  • Sin deriva: mi solución realiza un seguimiento exacto de los tiempos en los que se supone que debe ejecutarse. No hay deriva dependiendo del tiempo de ejecución (como en muchas otras soluciones).
  • Omitir: mi solución omitirá las tareas si una ejecución tomó demasiado tiempo (por ejemplo, hacer X cada cinco segundos, pero X tomó 6 segundos). Este es el comportamiento cron estándar (y por una buena razón). Muchas otras soluciones simplemente ejecutan la tarea varias veces seguidas sin demora. Para la mayoría de los casos (por ejemplo, tareas de limpieza) esto no es deseable. Si se deseaba, sólo tiene que utilizar next_time += delayen su lugar.

2
La mejor respuesta para no ir a la deriva.
Sebastian Stark

1
@PirateApp Haría esto en un hilo diferente. Usted podria hacerlo en el mismo hilo, pero entonces terminar la programación de su propio sistema de programación que es demasiado complejo para un comentario.
Alfe

1
En Python, gracias a GIL, acceder a variables en dos hilos es perfectamente seguro. Y la mera lectura en dos hilos nunca debería ser un problema (tampoco en otros entornos de hilos). Solo escribir desde dos hilos diferentes en un sistema sin un GIL (por ejemplo, en Java, C ++, etc.) necesita alguna sincronización explícita.
Alfe

1
@ user50473 Sin más información, primero abordaría la tarea desde el lado roscado. Un hilo lee los datos de vez en cuando y luego duerme hasta que es hora de hacerlo nuevamente. La solución anterior podría usarse para hacer esto, por supuesto. Pero podría imaginarme un montón de razones para ir por un camino diferente. Así que buena suerte :)
Alfe

1
El reposo se puede reemplazar por subprocesos. Incluso espere con tiempo de espera para ser más receptivo al salir de la aplicación. stackoverflow.com/questions/29082268/…
themadmax

20

Aquí hay una actualización del código de MestreLion que evita la deriva con el tiempo.

La clase RepeatedTimer aquí llama a la función dada cada segundo "intervalo" segundos según lo solicitado por el OP; la programación no depende de cuánto tiempo tarda la función en ejecutarse. Me gusta esta solución ya que no tiene dependencias de bibliotecas externas; Esto es simplemente Python puro.

import threading 
import time

class RepeatedTimer(object):
  def __init__(self, interval, function, *args, **kwargs):
    self._timer = None
    self.interval = interval
    self.function = function
    self.args = args
    self.kwargs = kwargs
    self.is_running = False
    self.next_call = time.time()
    self.start()

  def _run(self):
    self.is_running = False
    self.start()
    self.function(*self.args, **self.kwargs)

  def start(self):
    if not self.is_running:
      self.next_call += self.interval
      self._timer = threading.Timer(self.next_call - time.time(), self._run)
      self._timer.start()
      self.is_running = True

  def stop(self):
    self._timer.cancel()
    self.is_running = False

Ejemplo de uso (copiado de la respuesta de MestreLion):

from time import sleep

def hello(name):
    print "Hello %s!" % name

print "starting..."
rt = RepeatedTimer(1, hello, "World") # it auto-starts, no need of rt.start()
try:
    sleep(5) # your long-running job goes here...
finally:
    rt.stop() # better in a try/finally block to make sure the program ends!

5

Me enfrenté a un problema similar hace algún tiempo. Puede ser http://cronus.readthedocs.org podría ayudar?

Para v0.2, el siguiente fragmento funciona

import cronus.beat as beat

beat.set_rate(2) # 2 Hz
while beat.true():
    # do some time consuming work here
    beat.sleep() # total loop duration would be 0.5 sec

4

La principal diferencia entre eso y cron es que una excepción matará al demonio para siempre. Es posible que desee ajustar con un receptor y registrador de excepciones.


4

Una posible respuesta:

import time
t=time.time()

while True:
    if time.time()-t>10:
        #run your task here
        t=time.time()

1
Esto está ocupado esperando, por lo tanto, muy malo.
Alfe

Buena solución para alguien que busca un temporizador sin bloqueo.
Noel

3

Terminé usando el módulo de programación . La API es buena.

import schedule
import time

def job():
    print("I'm working...")

schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)
schedule.every(5).to(10).minutes.do(job)
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)
schedule.every().minute.at(":17").do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

Me está costando mucho tratar de usar este módulo en particular, necesito desbloquear el hilo principal, he revisado las preguntas frecuentes en el sitio web de documentación del programa, pero realmente no entiendo la solución provista. ¿Alguien sabe dónde puedo encontrar un ejemplo de trabajo que no bloquee el hilo principal?
5Daydreams

1

Yo uso Tkinter después de método (), que no "robar el juego" (como el sched módulo que fue presentado anteriormente), es decir, permite otras cosas funcionen en paralelo:

import Tkinter

def do_something1():
  global n1
  n1 += 1
  if n1 == 6: # (Optional condition)
    print "* do_something1() is done *"; return
  # Do your stuff here
  # ...
  print "do_something1() "+str(n1)
  tk.after(1000, do_something1)

def do_something2(): 
  global n2
  n2 += 1
  if n2 == 6: # (Optional condition)
    print "* do_something2() is done *"; return
  # Do your stuff here
  # ...
  print "do_something2() "+str(n2)
  tk.after(500, do_something2)

tk = Tkinter.Tk(); 
n1 = 0; n2 = 0
do_something1()
do_something2()
tk.mainloop()

do_something1()y do_something2()puede correr en paralelo y en cualquier velocidad de intervalo. Aquí, el segundo se ejecutará el doble de rápido. Tenga en cuenta también que he usado un contador simple como condición para terminar cualquiera de las funciones. Puede usar cualquier otra configuración que desee o ninguna si desea ejecutar una función hasta que finalice el programa (por ejemplo, un reloj).


Tenga cuidado con su redacción: afterno permite que las cosas se ejecuten en paralelo. Tkinter es de un solo subproceso y solo puede hacer una cosa a la vez. Si afterse ejecuta algo programado por , no se ejecuta en paralelo con el resto del código. Si ambos do_something1y do_something2están programados para ejecutarse al mismo tiempo, se ejecutarán secuencialmente, no en paralelo.
Bryan Oakley

@Apostolos lo único que hace su solución es usar el tkinter mainloop en lugar del sched mainloop, por lo que funciona exactamente de la misma manera pero permite que las interfaces tkinter continúen respondiendo. Si no está utilizando tkinter para otras cosas, entonces no cambia nada con respecto a la solución programada. Puede usar dos o más funciones programadas con diferentes intervalos en la schedsolución y funcionará exactamente igual que la suya.
nosklo

No, no funciona de la misma manera. Le expliqué esto. El uno "bloquea" el programa (es decir, detiene el flujo, no puede hacer nada más, ni siquiera comenzar otro trabajo programado como sugiere) hasta que finalice y el otro deje sus manos libres (es decir, puede hacerlo otras cosas después de que ha comenzado. No tienes que esperar hasta que termine. Esta es una gran diferencia. Si hubieras probado el método que presenté, lo habrías visto por ti mismo. He probado el tuyo. ¿Por qué no lo haces? probar el mío también?
Apostolos

1

Aquí hay una versión adaptada al código de MestreLion. Además de la función original, este código:

1) agregue first_interval utilizado para disparar el temporizador en un momento específico (la persona que llama necesita calcular el first_interval y pasar)

2) resuelve una condición de carrera en el código original. En el código original, si el hilo de control no pudo cancelar el temporizador en ejecución ("Detenga el temporizador y cancele la ejecución de la acción del temporizador. Esto solo funcionará si el temporizador todavía está en su etapa de espera". Citado en https: // docs.python.org/2/library/threading.html ), el temporizador se ejecutará sin fin.

class RepeatedTimer(object):
def __init__(self, first_interval, interval, func, *args, **kwargs):
    self.timer      = None
    self.first_interval = first_interval
    self.interval   = interval
    self.func   = func
    self.args       = args
    self.kwargs     = kwargs
    self.running = False
    self.is_started = False

def first_start(self):
    try:
        # no race-condition here because only control thread will call this method
        # if already started will not start again
        if not self.is_started:
            self.is_started = True
            self.timer = Timer(self.first_interval, self.run)
            self.running = True
            self.timer.start()
    except Exception as e:
        log_print(syslog.LOG_ERR, "timer first_start failed %s %s"%(e.message, traceback.format_exc()))
        raise

def run(self):
    # if not stopped start again
    if self.running:
        self.timer = Timer(self.interval, self.run)
        self.timer.start()
    self.func(*self.args, **self.kwargs)

def stop(self):
    # cancel current timer in case failed it's still OK
    # if already stopped doesn't matter to stop again
    if self.timer:
        self.timer.cancel()
    self.running = False

1

Esto parece una solución mucho más simple que aceptada: ¿tiene algunas deficiencias que no estoy considerando? Vine aquí buscando un poco de pasta copia simple y me decepcionó.

import threading, time

def print_every_n_seconds(n=2):
    while True:
        print(time.ctime())
        time.sleep(n)

thread = threading.Thread(target=print_every_n_seconds, daemon=True)
thread.start()

Que sale asincrónicamente.

#Tue Oct 16 17:29:40 2018
#Tue Oct 16 17:29:42 2018
#Tue Oct 16 17:29:44 2018

Tiene una deriva en el sentido de que si la tarea que se ejecuta lleva una cantidad de tiempo considerable, el intervalo se convierte en 2 segundos + tiempo de tarea, por lo que si necesita una programación precisa, entonces esto no es para usted.

Tenga en cuenta que la daemon=Truebandera significa que este hilo no bloqueará el cierre de la aplicación. Por ejemplo, tuve un problema en el que pytestse colgaría indefinidamente después de ejecutar las pruebas esperando que cesara este ataque.


No, imprime solo la primera fecha y hora y luego se detiene ...
Alex Poca

¿Estás seguro? Acabo de copiar y pegar en la terminal. Vuelve de inmediato pero la impresión continúa en segundo plano para mí.
Adam Hughes

Parece que me falta algo aquí. Puedo copiar / pegar el código en test.py , y correr con test.py pitón . Con Python2.7 necesito eliminar daemon = True que no se reconoce y leo varias impresiones. Con Python3.8 se detiene después de la primera impresión y ningún proceso está activo después de su finalización. Eliminando daemon = True Leí varias impresiones ...
Alex Poca

hmm extraño - estoy en Python 3.6.10 pero no sé por qué eso importaría
Adam Hughes

Nuevamente: Python3.4.2 (Debian GNU / Linux 8 (jessie)), tuvo que eliminar daemon = True para que pueda imprimir varias veces. Con daemon me sale un error de sintaxis. Las pruebas anteriores con Python2.7 y 3.8 estaban en Ubuntu 19.10 ¿Podría ser que el demonio se trata de manera diferente de acuerdo con el sistema operativo?
Alex Poca

0

Lo uso para causar 60 eventos por hora y la mayoría de los eventos ocurren en la misma cantidad de segundos después de todo el minuto:

import math
import time
import random

TICK = 60 # one minute tick size
TICK_TIMING = 59 # execute on 59th second of the tick
TICK_MINIMUM = 30 # minimum catch up tick size when lagging

def set_timing():

    now = time.time()
    elapsed = now - info['begin']
    minutes = math.floor(elapsed/TICK)
    tick_elapsed = now - info['completion_time']
    if (info['tick']+1) > minutes:
        wait = max(0,(TICK_TIMING-(time.time() % TICK)))
        print ('standard wait: %.2f' % wait)
        time.sleep(wait)
    elif tick_elapsed < TICK_MINIMUM:
        wait = TICK_MINIMUM-tick_elapsed
        print ('minimum wait: %.2f' % wait)
        time.sleep(wait)
    else:
        print ('skip set_timing(); no wait')
    drift = ((time.time() - info['begin']) - info['tick']*TICK -
        TICK_TIMING + info['begin']%TICK)
    print ('drift: %.6f' % drift)

info['tick'] = 0
info['begin'] = time.time()
info['completion_time'] = info['begin'] - TICK

while 1:

    set_timing()

    print('hello world')

    #random real world event
    time.sleep(random.random()*TICK_MINIMUM)

    info['tick'] += 1
    info['completion_time'] = time.time()

Dependiendo de las condiciones reales, puede obtener garrapatas de longitud:

60,60,62,58,60,60,120,30,30,60,60,60,60,60...etc.

pero al cabo de 60 minutos tendrás 60 ticks; y la mayoría de ellos ocurrirán en el desplazamiento correcto al minuto que prefiera.

En mi sistema obtengo una deriva típica de <1/20 de segundo hasta que surge la necesidad de corrección.

La ventaja de este método es la resolución de la deriva del reloj; lo que puede causar problemas si está haciendo cosas como agregar un elemento por marca y espera 60 elementos agregados por hora. No tener en cuenta la deriva puede causar indicaciones secundarias, como promedios móviles, para considerar datos demasiado profundos en el pasado, lo que resulta en una salida defectuosa.


0

por ejemplo, Mostrar la hora local actual

import datetime
import glib
import logger

def get_local_time():
    current_time = datetime.datetime.now().strftime("%H:%M")
    logger.info("get_local_time(): %s",current_time)
    return str(current_time)

def display_local_time():
    logger.info("Current time is: %s", get_local_time())
    return True

# call every minute
glib.timeout_add(60*1000, display_local_time)

0
    ''' tracking number of times it prints'''
import threading

global timeInterval
count=0
def printit():
  threading.Timer(timeInterval, printit).start()
  print( "Hello, World!")
  global count
  count=count+1
  print(count)
printit

if __name__ == "__main__":
    timeInterval= int(input('Enter Time in Seconds:'))
    printit()

Sobre la base de la entrada del usuario, iterará ese método en cada intervalo de tiempo.
raviGupta

0

Aquí hay otra solución sin usar ninguna biblioteca adicional.

def delay_until(condition_fn, interval_in_sec, timeout_in_sec):
    """Delay using a boolean callable function.

    `condition_fn` is invoked every `interval_in_sec` until `timeout_in_sec`.
    It can break early if condition is met.

    Args:
        condition_fn     - a callable boolean function
        interval_in_sec  - wait time between calling `condition_fn`
        timeout_in_sec   - maximum time to run

    Returns: None
    """
    start = last_call = time.time()
    while time.time() - start < timeout_in_sec:
        if (time.time() - last_call) > interval_in_sec:
            if condition_fn() is True:
                break
            last_call = time.time()
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.