Как выполнить функцию асинхронно каждые 60 секунд в Python?


Я хочу выполнять функцию каждые 60 секунд на Python, но я не хочу быть заблокирован между тем.

Как я могу сделать это асинхронно?

import threading
import time

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

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

С помощью этого кода функция f выполняется каждые 3 секунды в течение 20 секунд.время. В конце концов это дает ошибку, и я думаю, что это потому, что резьба.таймер никто не отменял.

Как я могу отменить его?

спасибо заранее!

7 53

7 ответов:

вы можете попробовать резьбу.Класс таймера: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()

Это зависит от того, что вы на самом деле хотите сделать в то же время. Потоки являются наиболее общим и наименее предпочтительным способом сделать это; вы должны знать о проблемах с потоками при его использовании: не все (не Python) код позволяет получить доступ из нескольких потоков одновременно, связь между потоками должна осуществляться с использованием потокобезопасных структур данных, таких как Queue.Queue, вы не сможете прервать поток извне, и завершение программы, пока поток все еще работает, может приведите к зависшему переводчику или ложным трассировкам.

часто есть более простой способ. Если вы делаете это в программе GUI, используйте функции таймера или события библиотеки GUI. У всех ги есть это. Аналогично, если вы используете другую систему событий, например Twisted или другую модель серверного процесса, вы должны иметь возможность подключаться к основному циклу событий, чтобы заставить его регулярно вызывать вашу функцию. Непоточные подходы действительно вызывают блокировку вашей программы, пока функция находится в ожидании, но не между вызовами функций.

самый простой способ-создать фоновый поток, который проходит ТО каждые 60 секунд. Тривиальная реализация:

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


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

timer = BackgroundTimer()
timer.start()

очевидно, что это, если "сделать что-то" занимает много времени, вам нужно будет приспособиться к нему в своем заявлении сна. Но это служит хорошим приближением.

я погуглил и нашел питона схемы Framework, которая делает возможным, чтобы подождать
для конкретного события.

The .callEvent(self, event, *channels) метод цепей содержит пожар и функциональность суспендировать-до-ответа, документация говорит:

запустить данное событие по указанным каналам и приостановить выполнение пока он не будет отправлен. Этот метод может быть вызван только как аргумент yield на верхнем уровне исполнения обработчика (например "yield self.callEvent(event)"). Он эффективно создает и возвращает генератор, который будет вызываться главным циклом до тех пор, пока событие не будет был отправлен (см.: func:circuits.core.handlers.handler).

Я надеюсь, что вы найдете его столь же полезным, как и я:)
./ с уважением

Если вы хотите вызвать метод "на часах" (например, каждый час в час), вы можете интегрировать следующую идею с любым механизмом нарезания резьбы, который вы выберете:

import time

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

Я думаю, что правильный способ запустить поток повторно следующий:

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

С помощью этого кода функция f выполняется каждые 3 секунды в течение 10 секунд.сна(10). В конце выполнения потока отменяется.

почему бы вам не создать выделенный поток, в который вы положили простой спальный петли:

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