Как остановить поток в Python на примерах

В этом уроке вы узнаете, как остановить поток в Python из main thread, используя класс Event модуля threading.

Содержание

Знакомство с объектом Event

Чтобы остановить поток, используйте класс Event модуля threading. Класс Event имеет внутренний логический флаг потокобезопасности, которому можно установить значение True или False. По умолчанию внутренний флаг имеет значение False.

В классе Event метод set() устанавливает внутренний флаг в значение True, а метод clear() сбрасывает флаг в значение False. Кроме того, метод is_set() возвращает True, если внутренний флаг установлен в True.

Чтобы остановить дочерний поток из основного потока, используйте объект Event, выполнив следующие шаги:

  • Сначала создайте новый объект Event и передайте его дочернему потоку.
  • Во-вторых, периодически проверяйте, установлен ли внутренний флаг объекта Event в дочернем потоке, вызывая метод is_set(), и останавливайте дочерний поток, если внутренний флаг был установлен.
  • В-третьих, в какой-то момент времени вызовите метод set() в основном потоке, чтобы остановить дочерний поток.

Следующая блок-схема иллюстрирует вышеуказанные шаги:

Блок-схема остановки потока в Python

Простой пример остановки потока в Python

В следующем примере показано, как использовать объект Event для остановки дочернего потока основного потока:

from threading import Thread, Event
from time import sleep

def task(event: Event) -> None:
    for i in range(6):
        print(f'Running #{i+1}')
        sleep(1)
        if event.is_set():
            print('The thread was stopped prematurely.')
            break
    else:
        print('The thread was stopped maturely.')

def main() -> None:

    event = Event()
    thread = Thread(target=task, args=(event,))
    
    # start the thread
    thread.start()

    # suspend  the thread after 3 seconds
    sleep(3)

    # stop the child thread
    event.set()    
   

if __name__ == '__main__':
    main()

Функция task()

Функция task() использует объект Event и возвращает None. Он будет выполнен в дочернем потоке:

def task(event: Event) -> None:
    for i in range(6):
        print(f'Running #{i+1}')
        sleep(1)
        if event.is_set():
            print('The thread was stopped prematurely.')
            break
    else:
        print('The thread was stopped maturely.')

Функция task() перебирает числа от 1 до 5. На каждой итерации мы используем функцию sleep(), чтобы задержать выполнение и выйти из цикла, если установлен внутренний флаг объекта event.

Функция main()

  • Сначала создайте новый объект Event:
event = Event()
  • Затем создайте новый поток, который выполняет функцию task() с объектом Event в качестве аргумента:
thread = Thread(target=task, args=(event,))
  • Затем начните выполнение дочернего потока:
thread.start()
  • После этого приостановите основной поток на три секунды:
sleep(3)
  • Наконец, установите внутренний флаг объекта Event в значение True, вызвав метод set(). Это также остановит дочерний поток:
event.set()

Остановка дочернего потока класса Thread

Иногда вам может потребоваться расширить класс Thread и переопределить метод run() для создания нового потока:

class MyThread(Thread):
    def run(self):
        pass

Чтобы остановить поток, использующий производный класс класса Thread, вы также используете объект Event модуля threading.

В следующем примере показано, как создать дочерний поток с использованием производного класса  Thread-класса и использовать объект Event для остановки дочернего потока из основного требуемого потока:

from threading import Thread, Event
from time import sleep

class Worker(Thread):
    def __init__(self, event, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.event = event

    def run(self) -> None:
        for i in range(6):
            print(f'Running #{i+1}')
            sleep(1)
            if self.event.is_set():
                print('The thread was stopped prematurely.')
                break
        else:
            print('The thread was stopped maturely.')

def main() -> None:

    # create a new Event object
    event = Event()

    # create a new Worker thread
    thread = Worker(event)
    
    # start the thread
    thread.start()

    # suspend  the thread after 3 seconds
    sleep(3)

    # stop the child thread
    event.set()    
   

if __name__ == '__main__':
    main()

Как это работает.

  • Сначала определите класс Worker, который расширяет класс Thread из модуля threading. Метод __init__() класса Worker принимает объект Event.
  • Во-вторых, переопределите метод run() класса Worker и используйте объект Event, чтобы остановить поток.
  • В-третьих, определите функцию main(), которая создает событие, рабочий поток, и передает объект Event в рабочий поток. Остальная логика такая же, как у функции main() в предыдущем примере.
Похожие посты
Добавить комментарий

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