Jak wykonywać funkcję asynchronicznie co 60 sekund w Pythonie?

Chcę wykonywać funkcję co 60 sekund w Pythonie, ale nie chcę być blokowany w międzyczasie.

Jak mogę to zrobić asynchronicznie?

import threading
import time

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

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

W tym kodzie funkcja f jest wykonywana co 3 sekundy w ciągu 20 sekund.czas. Na koniec daje błąd i myślę, że to dlatego, że gwintowanie.timer nie został anulowany.

Jak mogę to anulować? Z góry dzięki!
Author: aF., 2010-02-08

7 answers

Możesz spróbować gwintowania.Klasa czasomierza: 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()
 91
Author: David Underhill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-30 19:12:23

To zależy od tego, co naprawdę chcesz robić w międzyczasie. Wątki są najbardziej ogólnym i najmniej preferowanym sposobem na zrobienie tego; powinieneś być świadomy problemów z wątkiem, gdy go używasz: nie cały (Nie-Pythonowy) kod pozwala na dostęp z wielu wątków jednocześnie, komunikacja między wątkami powinna odbywać się przy użyciu bezpiecznych dla wątków struktur danych, takich jak Queue.Queue, nie będziesz w stanie przerwać wątku spoza niego, a zakończenie programu, gdy wątek jest nadal uruchomiony, może prowadzić do przerwania wątku. do powieszonego tłumacza lub fałszywych śladów.

Często jest łatwiejszy sposób. Jeśli robisz to w programie GUI, użyj funkcji timer lub event biblioteki GUI. Wszystkie GUI mają to. Podobnie, jeśli używasz innego systemu zdarzeń, takiego jak Twisted lub inny model procesu serwerowego, powinieneś być w stanie podłączyć się do głównej pętli zdarzeń, aby spowodować regularne wywoływanie funkcji. Podejścia bez wątków powodują blokowanie programu podczas oczekiwania na funkcję, ale nie między funkcjami.
 2
Author: Thomas Wouters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-08 16:51:45

Najprostszym sposobem jest utworzenie wątku tła, który uruchamia coś co 60 sekund. Trywialną implementacją jest:

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


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

timer = BackgroundTimer()
timer.start()

Oczywiście, jeśli to "zrób coś" zajmuje dużo czasu, będziesz musiał dostosować się do tego w swoim oświadczeniu o śnie. Ale to służy jako dobre przybliżenie.

 2
Author: 0xfe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-08 17:02:53

Poszperałem w googlach i znalazłem Framework Pythona circuits , który umożliwia czekanie
na konkretne wydarzenie.

Metoda .callEvent(self, event, *channels) obwodów zawiera funkcję fire i suspend-until-response, dokumentacja mówi:

Uruchom dane zdarzenie do określonych kanałów i Zawiesz wykonanie dopóki nie zostanie wysłana. Ta metoda może być wywołana tylko jako argument do yield na najwyższym poziomie wykonania obsługi (np. "yield self.callEvent(event)"). Informatyka skutecznie tworzy i zwraca generator, który będzie wywoływany przez główną pętlę, dopóki zdarzenie nie zostały wysłane(patrz: func: circuits.core.handlers.handler).

Mam nadzieję, że uznasz go za równie przydatny jak ja:)
./ regards

 2
Author: synner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 10:13:36

Jeśli chcesz wywołać metodę " on the clock "(np. co godzinę on the hour), możesz zintegrować następujący pomysł z dowolnym mechanizmem wątkowym, który wybierzesz:

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
Author: user1054050,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-01 21:49:25

Myślę, że dobrym sposobem na wielokrotne uruchamianie wątku jest następny:

import threading
import time

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

if __name__ == '__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()

Z tym kodem funkcja f jest wykonywana co 3 sekundy w ciągu 10 sekund.sen(10) Na końcu uruchamianie wątku jest anulowane.

 1
Author: syviad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-06 09:10:15

Dlaczego nie stworzysz dedykowanego wątku, w którym umieścisz prostą pętlę spania:

#!/usr/bin/env python
import time
while True:
   # Your code here
   time.sleep(60)
 0
Author: Aif,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-11 20:16:10