Эквивалент Python для setInterval ()? - PullRequest
31 голосов
/ 23 апреля 2010

Имеет ли Python функцию, аналогичную setInterval()?

в JavaScript

Спасибо

Ответы [ 15 ]

0 голосов
/ 23 июня 2017

Некоторые ответы выше, использующие func_wrapper и threading.Timer, действительно работают, за исключением того, что он порождает новый поток каждый раз, когда вызывается интервал, что вызывает проблемы с памятью.

В базовом примере ниже примерно реализован аналогичный механизм, помещающий интервал в отдельный поток.Он спит с заданным интервалом.Прежде чем переходить к коду, вот некоторые ограничения, о которых вам нужно знать:

  1. JavaScript является однопоточным, поэтому, когда функция внутри setInterval запускается, больше ничего не будетработать одновременно (исключая рабочий поток, но давайте поговорим об общем случае использования setInterval. Следовательно, многопоточность безопасна. Но здесь, в этой реализации, вы можете столкнуться с условиями гонки, если не используете threading.rLock.

  2. Приведенная ниже реализация использует time.sleep для имитации интервалов, но если добавить время выполнения func, общее время для этого интервала может оказаться больше, чем вы ожидаете.в зависимости от вариантов использования, вы можете захотеть «меньше спать» (минус время, потраченное на вызов func)

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


Хватит говорить, вот код:

# Python 2.7
import threading
import time


class Interval(object):
    def __init__(self):
        self.daemon_alive = True
        self.thread = None # keep a reference to the thread so that we can "join"

    def ticktock(self, interval, func):
        while self.daemon_alive:
            time.sleep(interval)
            func()

num = 0
def print_num():
    global num
    num += 1
    print 'num + 1 = ', num

def print_negative_num():
    global num
    print '-num = ', num * -1

intervals = {} # keep track of intervals
g_id_counter = 0 # roughly generate ids for intervals

def set_interval(interval, func):
    global g_id_counter

    interval_obj = Interval()
    # Put this interval on a new thread
    t = threading.Thread(target=interval_obj.ticktock, args=(interval, func))
    t.setDaemon(True)
    interval_obj.thread = t
    t.start()

    # Register this interval so that we can clear it later
    # using roughly generated id
    interval_id = g_id_counter
    g_id_counter += 1
    intervals[interval_id] = interval_obj

    # return interval id like it does in JavaScript
    return interval_id

def clear_interval(interval_id):
    # terminate this interval's while loop
    intervals[interval_id].daemon_alive = False
    # kill the thread
    intervals[interval_id].thread.join()
    # pop out the interval from registry for reusing
    intervals.pop(interval_id)

if __name__ == '__main__':
    num_interval = set_interval(1, print_num)
    neg_interval = set_interval(3, print_negative_num)

    time.sleep(10) # Sleep 10 seconds on main thread to let interval run
    clear_interval(num_interval)
    clear_interval(neg_interval)
    print "- Are intervals all cleared?"
    time.sleep(3) # check if both intervals are stopped (not printing)
    print "- Yup, time to get beers"

Exожидаемый вывод:

num + 1 =  1
num + 1 =  2
-num =  -2
 num + 1 =  3
num + 1 =  4
num + 1 =  5
-num =  -5
num + 1 =  6
num + 1 =  7
num + 1 =  8
-num =  -8
num + 1 =  9
num + 1 =  10
-num =  -10
Are intervals all cleared?
Yup, time to get beers
0 голосов
/ 04 октября 2016

Приведенный выше метод не совсем сделал это для меня, так как мне нужно было иметь возможность отменить интервал. Я превратил функцию в класс и придумал следующее:

class setInterval():
    def __init__(self, func, sec):
        def func_wrapper():
            self.t = threading.Timer(sec, func_wrapper)
            self.t.start()
            func()
        self.t = threading.Timer(sec, func_wrapper)
        self.t.start()

    def cancel(self):
        self.t.cancel()
0 голосов
/ 18 марта 2014

В последнее время у меня та же проблема, что и у вас.И я нахожу эти растворения:

1.Вы можете использовать библиотеку: threading.Time (здесь есть введение выше)

2.Вы можете использовать библиотеку: sched (здесь тоже есть введение)

3.Вы можете использовать библиотеку: Расширенный планировщик Python (Рекомендовать)

0 голосов
/ 23 апреля 2010

С Документация Python :

from threading import Timer

def hello():
    print "hello, world"

t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
0 голосов
/ 23 апреля 2010

В Python все по-другому: вам нужно либо sleep() (если вы хотите заблокировать текущий поток), либо начать новый поток. Смотри http://docs.python.org/library/threading.html

...