Python - Планировка потоков

Привет, будущие мастера Python! Сегодня мы погружаемся в увлекательный мир планировки потоков в Python. Не волнуйтесь, если вы новичок в программировании; я веду вас шаг за шагом, как я делал это для многих студентов на протяжении многих лет своей преподавательской деятельности. Давайте начнем эту захватывающую приключение вместе!

Python - Thread Scheduling

Понимание потоков

Перед тем как перейти к планировке, быстро пересмотрим, что такое потоки. Представьте себе, что вы читаете книгу, слушая музыку. Ваш мозг фактически выполняет два "потока" одновременно — один для чтения и один для слушания. В программировании потоки работают аналогично, позволяя программе выполнять несколько задач одновременно.

Планировка потоков с использованием класса Timer

Теперь давайте рассмотрим наш первый метод планирования потоков: класс Timer. Это как установка будильника для вашего кода!

Что такое класс Timer?

Класс Timer является частью модуля threading Python. Он позволяет вам запланировать выполнение функции после определенной задержки. Представьте себе, что вы говорите Python: "Эй, выполните для меня эту задачу, но подождите немного перед началом!"

Как использовать класс Timer

Рассмотрим простой пример:

import threading
import time

def greet(name):
print(f"Привет, {name}! Время: {time.strftime('%H:%M:%S')}")

# Создаем объект Timer
t = threading.Timer(5, greet, args=["Алиса"])

# Запускаем таймер
t.start()

print("Таймер запущен!")

# Дожидаемся завершения таймера
t.join()

print("Таймер завершен!")

Разберем это:

  1. Мы импортируем необходимые модули: threading и time.
  2. Мы определяем простую функцию greet, которая выводит приветствие с текущим временем.
  3. Мы создаем объект Timer, указывая ему выполнить функцию greet после 5-секундной задержки, передавая "Алиса" в качестве аргумента.
  4. Мы запускаем таймер с помощью t.start().
  5. Мы используем t.join(), чтобы дождаться завершения таймера перед продолжением.

Когда вы выполните это, вы увидите "Таймер запущен!" сразу, а затем после 5-секундной паузы — приветствие, а после — "Таймер завершен!".

Отмена таймера

Иногда вам может понадобиться отменить запланированную задачу. Это как решение не нуждаться в будильнике. Вот как это сделать:

import threading
import time

def task():
print("Эта задача не будет выполнена!")

t = threading.Timer(5, task)
t.start()

print("Таймер запущен, но мы отменим его...")
time.sleep(2)  # Дожидаемся 2 секунды
t.cancel()  # Отменяем таймер
print("Таймер отменен!")

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

Планировка потоков с использованием модуля sched

Теперь поднимемся на уровень выше и рассмотрим модуль sched. Если класс Timer похож на простой будильник, то модуль sched — это уже полноценное приложение для планирования!

Что такое модуль sched?

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

Как использовать модуль sched

Рассмотрим пример:

import sched
import time

# Создаем объект планировщика
s = sched.scheduler(time.time, time.sleep)

def print_time(name):
print(f"Привет, {name}! Время: {time.strftime('%H:%M:%S')}")

# Планируем некоторые события
s.enter(2, 1, print_time, argument=("Алиса",))
s.enter(4, 2, print_time, argument=("Боб",))
s.enter(6, 3, print_time, argument=("Чарли",))

print("Планировщик запущен!")
s.run()
print("Планировщик завершен!")

Разберем это:

  1. Мы создаем объект планировщика с помощью sched.scheduler().
  2. Мы определяем простую функцию print_time.
  3. Мы планируем три события с помощью s.enter():
  • Первый аргумент — это задержка в секундах.
  • Второй — приоритет (меньшие числа — высший приоритет).
  • Третий — функция для выполнения.
  • Ключевое слово argument позволяет передать аргументы в функцию.
  1. Мы запускаем планировщик с помощью s.run().

Когда вы выполните это, вы увидите приветствия, выводимые с интервалом в 2 секунды.

Отмена запланированных событий

Так же, как и с Timer, вы можете отменить запланированные события в sched:

import sched
import time

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

def task(name):
print(f"Привет, {name}!")

event1 = s.enter(2, 1, task, argument=("Алиса",))
event2 = s.enter(4, 1, task, argument=("Боб",))

print("События запланированы. Отменяем событие Боба...")
s.cancel(event2)

s.run()
print("Планировщик завершен!")

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

Сравнение Timer и sched

Вот быстрое сравнение двух методов, которые мы изучили:

Характеристика Timer sched
Легкость использования Простой, прямолинейный Более сложный, но более мощный
Несколько событий Один за раз Может планировать несколько событий
Точность Менее точный Более точный
Отмена Можно отменить перед выполнением Можно отменить в любое время
Применение Простые задержки Сложные потребности в планировании

Заключение

Итак, это было! Мы сделали путешествие по миру планировки потоков в Python, от простого класса Timer до более сложного модуля sched. Помните, как и при обучении езде на велосипеде, мастерство в этих концепциях требует практики. Так что не стесняйтесь экспериментировать и делать ошибки — именно так мы учимся!

На протяжении многих лет моей преподавательской деятельности я видел, как студенты переходят от полного новичка до профессионалов Python, и я уверен, что вы тоже можете это сделать. Продолжайте программировать, учиться и, что самое важное, наслаждайтесь этим процессом!

До встречи в следующий раз, счастливого кодирования!

Credits: Image by storyset