Я хочу выполнить функцию каждые 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 секунд time.time. В конце это дает ошибку, и я думаю, что это - потому что threading.timer не был отменен.
Как я могу отменить его?
Заранее спасибо!
Вы можете попробовать класс 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()
Это зависит от того, что вы действительно хотите делать в это время. Потоки - наиболее общий и наименее предпочтительный способ сделать это; вы должны знать о проблемах с потоковой передачей, когда вы ее используете: не весь код (кроме Python) разрешает доступ из нескольких потоков одновременно, связь между потоками должна осуществляться с использованием потоковобезопасных структур данных, таких как Queue.Queue
, вы не сможете прервать поток извне, а завершение программы, пока поток все еще работает, может привести к зависанию интерпретатора или ложным обратным трассировкам.
Часто есть более простой способ. Если вы делаете это в программе с графическим интерфейсом, используйте функцию таймера или событий библиотеки графического интерфейса. Это есть во всех графических интерфейсах. Точно так же, если вы используете другую систему событий, например 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()
Очевидно, что если «сделать что-то» занимает много времени, вам нужно учесть это в своем операторе сна. Но это хорошее приближение.
Почему бы вам не создать выделенный поток, в который вы помещаете простой цикл ожидания:
#!/usr/bin/env python
import time
while True:
# Your code here
time.sleep(60)