web-dev-qa-db-fra.com

Comment exécuter une fonction de manière asynchrone toutes les 60 secondes en Python?

Je veux exécuter une fonction toutes les 60 secondes sur Python mais je ne veux pas être bloqué en attendant.

Comment puis-je le faire de manière asynchrone?

import threading
import time

def f():
    print("hello world")
    threading.Timer(3, f).start()

if __== '__main__':
    f()    
    time.sleep(20)

Avec ce code, la fonction f est exécutée toutes les 3 secondes dans le délai de 20 secondes. À la fin, cela donne une erreur et je pense que c'est parce que le threading.timer n'a pas été annulé.

Comment puis-je l'annuler?

Merci d'avance!

57
aF.

Vous pouvez essayer la classe threading.Timer: http://docs.python.org/library/threading.html#timer-objects .

import threading

def f(f_stop):
    # do something here ...
    if not f_stop.is_set():
        # call f() again in 60 seconds
        threading.Timer(60, f, [f_stop]).start()

f_stop = threading.Event()
# start calling f now and every 60 sec thereafter
f(f_stop)

# stop the thread when needed
#f_stop.set()
100
David Underhill

Le moyen le plus simple consiste à créer un thread d'arrière-plan qui exécute quelque chose toutes les 60 secondes. Une implémentation triviale est:

class BackgroundTimer(Thread):   
   def run(self):
      while 1:
        Time.sleep(60)
        # do something


# ... SNIP ...
# Inside your main thread
# ... SNIP ...

timer = BackgroundTimer()
timer.start()

De toute évidence, si le "faire quelque chose" prend du temps, vous devrez en tenir compte dans votre déclaration de sommeil. Mais cela sert de bonne approximation.

2
0xfe

Cela dépend de ce que vous voulez réellement faire dans l'intervalle. Les threads sont le moyen le plus général et le moins préféré de le faire; vous devez être conscient des problèmes de threading lorsque vous l'utilisez: tout le code (non-Python) n'autorise pas l'accès à partir de plusieurs threads simultanément, la communication entre les threads doit être effectuée en utilisant des infrastructures de données thread-safe comme Queue.Queue, vous ne pourrez pas interrompre le thread depuis l'extérieur, et terminer le programme alors que le thread est toujours en cours d'exécution peut conduire à un interpréteur bloqué ou à des retraits parasites.

Il existe souvent un moyen plus simple. Si vous faites cela dans un programme GUI, utilisez le temporisateur de la bibliothèque GUI ou la fonctionnalité d'événement. Toutes les interfaces graphiques ont cela. De même, si vous utilisez un autre système d'événements, comme Twisted ou un autre modèle de processus serveur, vous devriez pouvoir vous connecter à la boucle d'événement principale pour qu'elle appelle régulièrement votre fonction. Les approches non-threading provoquent le blocage de votre programme pendant que la fonction est en attente, mais pas entre les appels de fonction.

2
Thomas Wouters

J'ai parcouru Google et trouvé le cadre Python circuits , qui permet d'attendre
pour un événement particulier.

La méthode .callEvent(self, event, *channels) des circuits contient une fonctionnalité d'incendie et de suspension jusqu'à réponse, la documentation indique:

Déclenchez l'événement donné sur les canaux spécifiés et suspendez l'exécution jusqu'à ce qu'il soit distribué. Cette méthode ne peut être invoquée que comme argument d'un yield au niveau d'exécution supérieur d'un gestionnaire (par exemple "yield self.callEvent(event)"). Il crée et renvoie efficacement un générateur qui sera invoqué par la boucle principale jusqu'à ce que l'événement ait été distribué (voir: func: circuits.core.handlers.handler).

J'espère que vous le trouverez aussi utile que moi :)
./Cordialement

2
synner

Je pense que la bonne façon d'exécuter un thread à plusieurs reprises est la suivante:

import threading
import time

def f():
    print("hello world")  # your code here
    myThread.run()

if __== '__main__':
    myThread = threading.Timer(3, f)  # timer is set to 3 seconds
    myThread.start()
    time.sleep(10)  # it can be loop or other time consuming code here
    if myThread.is_alive():
        myThread.cancel()

Avec ce code, la fonction f est exécutée toutes les 3 secondes dans les 10 secondes de time.sleep (10). À la fin, l'exécution du thread est annulée.

1
syviad

Si vous souhaitez invoquer la méthode "sur l'horloge" (par exemple toutes les heures sur l'heure), vous pouvez intégrer l'idée suivante avec le mécanisme de filetage que vous choisissez:

import time

def wait(n):
    '''Wait until the next increment of n seconds'''
    x = time.time()
    time.sleep(n-(x%n))
    print time.asctime()
1
user1054050

Pourquoi ne créez-vous pas un fil dédié, dans lequel vous mettez une simple boucle de sommeil:

#!/usr/bin/env python
import time
while True:
   # Your code here
   time.sleep(60)
0
Aif