Как выполнить функцию асинхронно каждые 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 ответов:
вы можете попробовать резьбу.Класс таймера: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). В конце выполнения потока отменяется.