Qual è il modo migliore per eseguire ripetutamente una funzione ogni x secondi?


284

Voglio eseguire ripetutamente una funzione in Python ogni 60 secondi per sempre (proprio come un NSTimer nell'Obiettivo C). Questo codice verrà eseguito come demone ed è effettivamente come chiamare lo script Python ogni minuto usando un cron, ma senza richiedere che sia impostato dall'utente.

In questa domanda su un cron implementato in Python , la soluzione sembra effettivamente solo sleep () per x secondi. Non ho bisogno di funzionalità così avanzate quindi forse qualcosa del genere funzionerebbe

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

Ci sono problemi prevedibili con questo codice?


84
Un punto pedante, ma può essere critico, il tuo codice sopra il codice non viene eseguito ogni 60 secondi, ma crea un intervallo di 60 secondi tra le esecuzioni. Succede solo ogni 60 secondi se il codice eseguito non richiede affatto tempo.
Simon,

4
time.sleep(60)può anche tornare sia prima che dopo
jfs

5
Mi chiedo ancora: ci sono problemi prevedibili con questo codice?
Banana,

1
Il "problema prevedibile" è che non puoi aspettarti 60 iterazioni all'ora semplicemente usando time.sleep (60). Quindi, se aggiungi un elemento per iterazione e mantieni un elenco di lunghezza impostata ... la media di tale elenco non rappresenterà un "periodo" di tempo coerente; quindi funzioni come "media mobile" possono fare riferimento a punti dati troppo vecchi, il che distorcerà la tua indicazione.
litepresence,

2
@Banana Sì, puoi aspettarti qualsiasi problema causato perché lo script non viene eseguito ESATTAMENTE ogni 60 secondi. Per esempio. Ho iniziato a fare qualcosa del genere per dividere i flussi video e caricarli e alla fine ho ricevuto streming di 5-10 ~ secondi in più perché la coda dei media è in buffer mentre elaboro i dati all'interno del ciclo. Dipende dai tuoi dati. Se la funzione è una sorta di semplice cane da guardia che ti avverte, ad esempio, quando il tuo disco è pieno, non dovresti avere problemi con questo.Se stai controllando un avviso di centrale nucleare, potresti finire con una città completamente fatto saltare in aria x
DGoiko

Risposte:


229

Se il tuo programma non ha già un ciclo di eventi, usa il modulo sched , che implementa un programmatore di eventi per scopi generici.

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

Se si sta già utilizzando una libreria di loop evento come asyncio, trio, tkinter, PyQt5, gobject, kivy, e molti altri - basta pianificare l'attività usando i metodi della vostra biblioteca ciclo di eventi esistenti, invece.


16
Il modulo sched serve per l'esecuzione delle funzioni di pianificazione dopo un po 'di tempo, come si usa per ripetere una chiamata di funzione ogni x secondi senza usare time.sleep ()?
Baishampayan Ghose,

2
@Baishampayan: basta programmare una nuova corsa.
nosklo,

3
Quindi anche apscheduler su pacchetti.python.org/APScheduler dovrebbe essere menzionato a questo punto.
Daniel F,

6
nota: questa versione potrebbe andare alla deriva. Puoi usarlo enterabs()per evitarlo. Ecco una versione non alla deriva per il confronto .
jfs,

8
@JavaSa: perché "fai le tue cose" non è istantaneo e time.sleepqui si possono accumulare errori . "Esegui ogni X secondi" ed "Esegui con un ritardo di ~ X secondi ripetutamente" non sono gli stessi. Vedi anche questo commento
jfs

180

Blocca il tuo ciclo temporale sull'orologio di sistema in questo modo:

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

22
+1. la tua e la twistedrisposta sono le uniche risposte che eseguono una funzione ogni xsecondo. Il resto esegue la funzione con un ritardo di xsecondi dopo ogni chiamata.
jfs,

13
Se dovessi aggiungere del codice a questo che impiegava più di un solo secondo ... Avrebbe buttato via il tempismo e avrebbe iniziato a rimanere indietro. La risposta accettata in questo caso è corretta ... Chiunque può ripetere un semplice comando di stampa e farlo funzionare ogni secondo senza indugio ...
Angry 84

5
Preferisco a from time import time, sleepcausa delle implicazioni esistenziali;)
Will

14
Funziona in modo fantastico. Non è necessario sottrarre il tuo starttimese inizi sincronizzandolo a un certo momento: time.sleep(60 - time.time() % 60)ha funzionato bene per me. L'ho usato come time.sleep(1200 - time.time() % 1200)e mi dà i registri :00 :20 :40, esattamente come volevo.
TemporalWolf

2
@AntonSchigur per evitare la deriva dopo più iterazioni. Un'iterazione individuo può iniziare leggermente prima o poi seconda sleep(), timer()precisione e il tempo necessario per eseguire il corpo del ciclo ma iterazioni media verificare sempre sui confini dell'intervallo (anche se alcuni sono saltato): while keep_doing_it(): sleep(interval - timer() % interval). Confrontalo con il punto in while keep_doing_it(): sleep(interval)cui si possono accumulare errori dopo diverse iterazioni.
jfs

72

Potresti prendere in considerazione Twisted, che è una libreria di rete Python che implementa il modello di reattore .

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

Mentre "while True: sleep (60)" probabilmente funzionerà, Twisted probabilmente implementa già molte delle funzionalità di cui avrete eventualmente bisogno (demonizzazione, registrazione o gestione delle eccezioni come sottolineato da Bobince) e sarà probabilmente una soluzione più solida


Ottima risposta, molto accurata senza deriva. Mi chiedo se questo metta in pausa anche la CPU in attesa di eseguire l'attività (ovvero non attesa in attesa)?
smoothware

1
questo va alla deriva al millisecondo livello
Derek Eden,

1
Che cosa significa "derive a livello di millisecondi"?
Jean-Paul Calderone,

Esiste un modo per interrompere il ciclo, diciamo dopo 10 minuti? @Aaron Mäenpää
Alper

67

Se vuoi un modo non bloccante per eseguire periodicamente la tua funzione, invece di un ciclo infinito bloccante userei un timer threaded. In questo modo il tuo codice può continuare a funzionare ed eseguire altre attività e avere comunque la tua funzione chiamata ogni n secondi. Uso molto questa tecnica per stampare informazioni sullo stato di avanzamento di attività lunghe, CPU / disco / rete.

Ecco il codice che ho pubblicato in una domanda simile, con controllo start () e 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!

Caratteristiche:

  • Solo libreria standard, nessuna dipendenza esterna
  • start()e stop()è sicuro chiamare più volte anche se il timer è già stato avviato / arrestato
  • La funzione da chiamare può avere argomenti posizionali e nominati
  • Puoi cambiare in intervalqualsiasi momento, sarà efficace dopo la prossima corsa. Lo stesso vale per args, kwargse anche function!

Questa soluzione sembra andare alla deriva nel tempo; Avevo bisogno di una versione che mirasse a chiamare la funzione ogni n secondi senza deriva. Pubblicherò un aggiornamento in una domanda separata.
Eraoul,

In def _run(self)Sto cercando di avvolgere la mia testa intorno perché si chiama self.start()prima self.function(). Puoi elaborare? Penserei che chiamare per start()primo self.is_runningsarebbe sempre Falsecosì, quindi avremmo sempre creato un nuovo thread.
Rich Episcopo,

1
Penso di esserci arrivato fino in fondo. La soluzione di @ MestreLion esegue una funzione ogni xsecondo (ovvero t = 0, t = 1x, t = 2x, t = 3x, ...) dove nei manifesti originali il codice di esempio esegue una funzione con intervallo di x secondi tra. Inoltre, questa soluzione credo abbia un bug se intervalè inferiore al tempo necessario functionper l'esecuzione. In tal caso, self._timerverrà sovrascritto nella startfunzione.
Rich Episcopo,

Sì, @RichieEpiscopo, la chiamata a .function()after .start()è di eseguire la funzione at = 0. E non penso che sarà un problema se functionimpiegherà più tempo interval, ma sì, ci potrebbero essere alcune condizioni di gara sul codice.
MestreLion,

Questo è l'unico modo non bloccante che potrei ottenere. Grazie.
backslashN

35

Il modo più semplice credo di essere:

import time

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

while True:
    executeSomething()

In questo modo il tuo codice viene eseguito, quindi attende 60 secondi, quindi viene eseguito di nuovo, attende, esegue, ecc ... Non è necessario complicare le cose: D


La parola chiave True dovrebbe essere maiuscola
Sean Cain il

39
In realtà questa non è la risposta: il tempo sleep () può essere usato solo per aspettare X secondi dopo ogni esecuzione. Ad esempio, se l'esecuzione della tua funzione richiede 0,5 secondi e usi time.sleep (1), significa che la tua funzione viene eseguita ogni 1,5 secondi, non 1. Dovresti usare altri moduli e / o thread per assicurarti che qualcosa funzioni per Y volte in ogni X secondi.
kommradHomer,

1
@kommradHomer: la risposta di Dave Rove dimostra che puoi usare time.sleep()run qualcosa ogni X secondi
jfs

2
Secondo me il codice dovrebbe chiamare time.sleep()in while Trueloop come:def executeSomething(): print('10 sec left') ; while True: executeSomething(); time.sleep(10)
Leonard Lepadatu il

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)

Se vuoi farlo senza bloccare il tuo codice rimanente, puoi usarlo per farlo funzionare nel suo thread:

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

Questa soluzione combina diverse funzionalità che raramente si trovano combinate nelle altre soluzioni:

  • Gestione delle eccezioni: per quanto possibile a questo livello, le eccezioni vengono gestite correttamente, ovvero vengono registrate per scopi di debug senza interrompere il nostro programma.
  • Nessun concatenamento: l'implementazione simile a una catena comune (per la pianificazione del prossimo evento) che si trova in molte risposte è fragile nell'aspetto che se qualcosa va storto all'interno del meccanismo di pianificazione ( threading.Timero qualsiasi altra cosa), questo terminerà la catena. Non verranno eseguite ulteriori esecuzioni, anche se la ragione del problema è già stata risolta. Un semplice ciclo e in attesa con un semplice sleep()è molto più robusto in confronto.
  • Nessuna deriva: la mia soluzione tiene traccia esatta dei tempi in cui dovrebbe funzionare. Non c'è deriva a seconda del tempo di esecuzione (come in molte altre soluzioni).
  • Salto: la mia soluzione salterà le attività se un'esecuzione impiegava troppo tempo (ad esempio, esegui X ogni cinque secondi, ma X impiegava 6 secondi). Questo è il comportamento cron standard (e per una buona ragione). Molte altre soluzioni eseguono semplicemente l'attività più volte di seguito senza alcun ritardo. Nella maggior parte dei casi (ad es. Attività di pulizia) questo non è desiderato. Se lo si desidera, utilizzare semplicemente next_time += delayinvece.

2
migliore risposta per non andare alla deriva.
Sebastian Stark,

1
@PirateApp Lo farei in un thread diverso. Si potrebbe farlo nello stesso thread, ma poi si finisce per programmare il proprio sistema di pianificazione che è troppo complesso per un commento.
Alfe,

1
In Python, grazie a GIL, l'accesso alle variabili in due thread è perfettamente sicuro. E la semplice lettura in due thread non dovrebbe mai essere un problema (anche non in altri ambienti thread). Solo la scrittura da due thread diversi in un sistema senza un GIL (ad esempio in Java, C ++, ecc.) Richiede una sincronizzazione esplicita.
Alfe,

1
@ user50473 Senza ulteriori informazioni, per prima cosa affronterei l'attività dal lato thread. Un thread legge i dati di tanto in tanto e poi dorme fino a quando è di nuovo il momento di farlo. La soluzione sopra potrebbe essere usata per fare questo ovviamente. Ma potrei immaginare un sacco di ragioni per andare in un altro modo. Quindi buona fortuna :)
Alfe,

1
La sospensione può essere sostituita tramite threading. Evitare di attendere con timeout per essere più reattivi all'uscita dall'applicazione. stackoverflow.com/questions/29082268/...
themadmax

20

Ecco un aggiornamento del codice da MestreLion che evita la derapata nel tempo.

La classe RepeatedTimer qui chiama la funzione data ogni "intervallo" secondi come richiesto dall'OP; la pianificazione non dipende da quanto tempo richiede l'esecuzione della funzione. Mi piace questa soluzione poiché non ha dipendenze da librerie esterne; questo è solo puro pitone.

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

Esempio di utilizzo (copiato dalla risposta di 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

Ho avuto un problema simile qualche tempo fa. Può essere http://cronus.readthedocs.org potrebbe aiutare?

Per v0.2, funziona il seguente frammento

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 differenza principale tra questo e cron è che un'eccezione ucciderà definitivamente il demone. Potresti voler avvolgere con un catcher e un logger di eccezioni.


4

Una possibile risposta:

import time
t=time.time()

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

1
Questo è occupato in attesa quindi un pessimo.
Alfe,

Buona soluzione per chi cerca un timer non bloccante.
Noel,

3

Ho finito per usare il modulo di pianificazione . L'API è carina.

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)

Sto facendo fatica a provare ad usare questo modulo in particolare, ho bisogno di sbloccare il thread principale, ho controllato le FAQ nel sito web della documentazione del programma, ma non ho davvero capito la soluzione fornita. Qualcuno sa dove posso trovare un esempio funzionante che non blocchi il thread principale?
5Daydreams il

1

Uso il metodo Tkinter after (), che non "ruba il gioco" (come il modulo sched che era stato presentato in precedenza), ovvero consente ad altre cose di funzionare in parallelo:

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()e do_something2()può funzionare in parallelo e con qualunque intervallo di velocità. Qui, il secondo verrà eseguito due volte più velocemente. Nota anche che ho usato un semplice contatore come condizione per terminare entrambe le funzioni. Puoi usare qualunque altra contesa ti piaccia o nessuna se quale funzione eseguire fino al termine del programma (ad es. Un orologio).


Fai attenzione con la tua formulazione: afternon consente alle cose di correre in parallelo. Tkinter è a thread singolo e può fare solo una cosa alla volta. Se qualcosa in programma afterè in esecuzione, non è in esecuzione in parallelo con il resto del codice. Se entrambi do_something1e do_something2sono programmati per eseguire contemporaneamente, che vengono eseguite in sequenza e non in parallelo.
Bryan Oakley,

@Apostolos non fa altro che utilizzare tkinter mainloop invece di sched mainloop, quindi funziona esattamente allo stesso modo ma consente alle interfacce tkinter di continuare a rispondere. Se non stai usando tkinter per altre cose, non cambia nulla per quanto riguarda la soluzione sched. È possibile utilizzare due o più funzioni pianificate con intervalli diversi nella schedsoluzione e funzionerà esattamente come la tua.
nosklo,

No, non funziona allo stesso modo. Ho spiegato questo. Uno "blocca" il programma (cioè interrompe il flusso, non puoi fare nient'altro - nemmeno iniziare un altro lavoro programmato come suggerisci) fino al termine e l'altro lascia le mani libere / libere (cioè puoi fare altre cose dopo che è iniziato. Non devi aspettare fino al termine. Questa è una grande differenza. Se avessi provato il metodo che ho presentato, avresti visto di persona. Ho provato il tuo. Perché non provare anche il mio?
Apostolos

1

Ecco una versione adattata al codice di MestreLion. Oltre alla funzione originale, questo codice:

1) aggiungi first_interval utilizzato per attivare il timer in un momento specifico (il chiamante deve calcolare il first_interval e passare)

2) risolvere una condizione di gara nel codice originale. Nel codice originale, se il thread di controllo non è riuscito a annullare il timer in esecuzione ("Arresta il timer e annulla l'esecuzione dell'azione del timer. Funzionerà solo se il timer è ancora nella sua fase di attesa." Citato da https: // docs.python.org/2/library/threading.html ), il timer funzionerà all'infinito.

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

Sembra una soluzione molto più semplice di quella accettata - presenta delle carenze che non sto prendendo in considerazione? Sono venuto qui alla ricerca di un po 'di pasta semplice e morta ed ero deluso.

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

Che produce in modo asincrono.

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

Ha una deriva nel senso che se l'attività in esecuzione richiede una notevole quantità di tempo, allora l'intervallo diventa 2 secondi + tempo dell'attività, quindi se hai bisogno di una pianificazione precisa, questo non fa per te.

Nota che il daemon=Trueflag indica che questo thread non bloccherà la chiusura dell'app. Ad esempio, si è verificato un problema a causa del quale pytestsi bloccherebbe indefinitamente dopo aver eseguito i test in attesa che cessasse questa testa.


No, stampa solo il primo datetime e poi si interrompe ...
Alex Poca,

Sei sicuro - ho appena copiato e incollato nel terminale. Torna subito ma la stampa continua in secondo piano per me.
Adam Hughes,

Sembra che mi manchi qualcosa qui. Copio / incollato il codice test.py , e correre con pitone test.py . Con Python2.7 ho bisogno di rimuovere daemon = True che non è riconosciuto e ho letto più stampe. Con Python3.8 si arresta dopo la prima stampa e nessun processo è attivo dopo la fine. Removing daemon = True Ho letto più stampe ...
Alex Poca il

hmm strano - Sono su Python 3.6.10 ma non so perché questo avrebbe importanza
Adam Hughes,

Ancora una volta: Python3.4.2 (Debian GNU / Linux 8 (jessie)), ha dovuto rimuovere daemon = True in modo da poter stampare più volte. Con demone ottengo un errore di sintassi. I precedenti test con Python2.7 e 3.8 erano su Ubuntu 19.10 Potrebbe essere che il demone sia trattato in modo diverso in base al sistema operativo?
Alex Poca,

0

Uso questo per causare 60 eventi all'ora con la maggior parte degli eventi che si verificano nello stesso numero di secondi dopo l'intero 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()

A seconda delle condizioni effettive potresti ricevere segni di spunta di lunghezza:

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

ma alla fine di 60 minuti avrai 60 tick; e la maggior parte si verificherà con l'offset corretto al minuto che preferisci.

Sul mio sistema ottengo una deriva tipica di <1/20 di secondo fino a quando non si presenta la necessità di una correzione.

Il vantaggio di questo metodo è la risoluzione della deriva dell'orologio; che può causare problemi se stai facendo cose come aggiungere un articolo per tick e ti aspetti 60 articoli aggiunti all'ora. La mancata spiegazione della deriva può causare indicazioni secondarie come le medie mobili che considerano i dati troppo profondi nel passato con conseguenti risultati errati.


0

ad es. Visualizza l'ora locale corrente

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

Sulla base dell'input dell'utente, itererà quel metodo in ogni intervallo di tempo.
raviGupta,

0

Ecco un'altra soluzione senza usare ulteriori librerie.

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()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.