Рубрики
Без рубрики

sched – Планировщик событий по времени

Автор оригинала: Doug Hellmann.

Цель:

Планировщик общих событий.

Модуль sched реализует общий планировщик событий для выполнения задач в определенное время. Класс планировщика использует функцию time для определения текущего времени и функцию delay для ожидания определенного периода времени. Фактические единицы времени не важны, что делает интерфейс достаточно гибким для использования во многих целях.

Функция time вызывается без аргументов и должна возвращать число, представляющее текущее время. Функция delay вызывается с одним целочисленным аргументом, использует тот же масштаб, что и функция времени, и должна ждать столько единиц времени, прежде чем вернуться. По умолчанию используются monotonic () и sleep () от времени, но в примерах в этом разделе используется time.time () , который также соответствует требованиям, поскольку делает вывод более понятным.

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

Запуск событий с задержкой

События могут быть запланированы на запуск после задержки или в определенное время. Чтобы запланировать их с задержкой, используйте метод enter () , который принимает четыре аргумента.

  • Число, представляющее задержку
  • Приоритетное значение
  • Функция для вызова
  • Набор аргументов функции

В этом примере планируется запуск двух разных событий через две и три секунды соответственно. Когда наступает время события, вызывается print_event () и печатает текущее время и аргумент имени, переданный событию.

sched_basic.py

import sched
import time

scheduler  sched.scheduler(time.time, time.sleep)


def print_event(name, start):
    now  time.time()
    elapsed  int(now - start)
    print('EVENT: {}>{}>{}'.format(
        time.ctime(now), elapsed, name))


start  time.time()
print('START:', time.ctime(start))
scheduler.enter(2, 1, print_event, ('first', start))
scheduler.enter(3, 1, print_event, ('second', start))

scheduler.run()

Запуск программы производит:

$ python3 sched_basic.py

START: Sun Sep  4 16:21:01 2016
EVENT: Sun Sep  4 16:21:03 2016 elapsed=2
EVENT: Sun Sep  4 16:21:04 2016 elapsed=3

Время, напечатанное для первого события, составляет две секунды после запуска, а время для второго события – три секунды после запуска.

Перекрывающиеся события

Вызов run () блокируется до тех пор, пока все события не будут обработаны. Каждое событие запускается в одном потоке, поэтому, если для выполнения события требуется больше времени, чем задержка между событиями, произойдет перекрытие. Наложение разрешается путем откладывания более позднего мероприятия. События не теряются, но некоторые события могут быть вызваны позже, чем было запланировано. В следующем примере long_event () находится в спящем режиме, но он может так же легко задержаться, выполняя длительные вычисления или блокируя ввод-вывод.

sched_overlap.py

import sched
import time

scheduler  sched.scheduler(time.time, time.sleep)


def long_event(name):
    print('BEGIN EVENT :', time.ctime(time.time()), name)
    time.sleep(2)
    print('FINISH EVENT:', time.ctime(time.time()), name)


print('START:', time.ctime(time.time()))
scheduler.enter(2, 1, long_event, ('first',))
scheduler.enter(3, 1, long_event, ('second',))

scheduler.run()

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

$ python3 sched_overlap.py

START: Sun Sep  4 16:21:04 2016
BEGIN EVENT : Sun Sep  4 16:21:06 2016 first
FINISH EVENT: Sun Sep  4 16:21:08 2016 first
BEGIN EVENT : Sun Sep  4 16:21:08 2016 second
FINISH EVENT: Sun Sep  4 16:21:10 2016 second

Приоритеты событий

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

sched_priority.py

import sched
import time

scheduler  sched.scheduler(time.time, time.sleep)


def print_event(name):
    print('EVENT:', time.ctime(time.time()), name)


now  time.time()
print('START:', time.ctime(now))
scheduler.enterabs(now + 2, 2, print_event, ('first',))
scheduler.enterabs(now + 2, 1, print_event, ('second',))

scheduler.run()

В этом примере необходимо убедиться, что они запланированы на одно и то же время, поэтому вместо enter () используется метод enterabs () . Первый аргумент функции enterabs () – это время запуска события, а не время задержки.

$ python3 sched_priority.py

START: Sun Sep  4 16:21:10 2016
EVENT: Sun Sep  4 16:21:12 2016 second
EVENT: Sun Sep  4 16:21:12 2016 first

Отмена событий

И enter () , и enterabs () возвращают ссылку на событие, которую можно использовать для его отмены позже. Поскольку run () блокируется, событие необходимо отменить в другом потоке. В этом примере запускается поток для запуска планировщика, а основной поток обработки используется для отмены события.

sched_cancel.py

import sched
import threading
import time

scheduler  sched.scheduler(time.time, time.sleep)

# Set up a global to be modified by the threads
counter  0


def increment_counter(name):
    global counter
    print('EVENT:', time.ctime(time.time()), name)
    counter  1
    print('NOW:', counter)


print('START:', time.ctime(time.time()))
e1  scheduler.enter(2, 1, increment_counter, ('E1',))
e2  scheduler.enter(3, 1, increment_counter, ('E2',))

# Start a thread to run the events
t  threading.Thread(targetscheduler.run)
t.start()

# Back in the main thread, cancel the first scheduled event.
scheduler.cancel(e1)

# Wait for the scheduler to finish running in the thread
t.join()

print('FINAL:', counter)

Было запланировано два мероприятия, но первое позже было отменено. Выполняется только второе событие, поэтому переменная счетчика увеличивается только один раз.

$ python3 sched_cancel.py

START: Sun Sep  4 16:21:13 2016
EVENT: Sun Sep  4 16:21:16 2016 E2
NOW: 1
FINAL: 1

Смотрите также