• Как правильно закрыть поток в python?

    Sly_tom_cat
    @Sly_tom_cat
    .
    А не надо извне закрывать потоки и процессы. Можно получить кучу неприятностей.
    В нормально проработанном решении потоки/процессы сами должны закрываться тогда, когда нужно. Если нужно управлять этим извне - то для этого и существуют примитивы типа семафоров/флагов/эвентов.

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

    "Коллектор":
    import threading
    def job(id, ...):
    global res
      <Подготовка блока данных>
      res[id] = <блок подготовленных данных>
      return
    
    res = []
    for i in range(N):   # запуск N потоков
        res.append(<пустой блок>)
        threading.Thread(target=job, args=(i, ...)).start()
    for th in threading.enumerate():  # ожидание всех потоков 
        if th != threading.currentThread():
          th.join()
    <здесь массив с блоками полностью собран >


    "Победитель":
    import threading
    def job(...):
      global val
      global event
      while <не нашли>
        <элементарный шаг поиска>
        if event.is_set():
          return   # кто-то уже нашел искомое
      val=<то что нашли>
      event.set()   # этот поток нашел искомое и радостно сообщает всем об этом
      return
    
    val = None  # искомое значение
    event = threading.Event() # флаг сигнализирующий о том что решение найдено
    threads = []
    for i in range(N):
        threads.append(threading.Thread(target=job, args=(i, ...)))
        threads[-1].start()
    event.wait()  # тут основной поток ждет сигнала о победе от одного из запущенных потоков
    # если есть шанс, что победителя может и не быть, то в wait() нужно указать таймаут
    # и читать значение event.wait(), что бы узнать - сработал таймаут или появился победитель.
    <тут обрабатываем найденное>
    for th in threads:   # Подчищаем за собой - гарантированно собираем закрывшиеся потоки
          th.join()


    ЗЫ последний цикл в "победителе" - часто не обязателен, но если сама эта процедура запущена во множестве потоков, то можно получить так называемый "потоковый потоп", когда потоки не успевают закрываться сами и плодятся в системе со страшной силой, с предсказуемыми последствиями.
    ЗЫЫ также обратите внимание на варианты работы с набором потоков. В примере "Коллектор" не подразумевается, что в программе есть какие-то еще потоки, поэтому сборка потоков идет всех, кроме текущего (основного потока программы). А вот в "Победитель" потоки сохраняются в списке и из этого списка потом собираются. Это позволяет иметь в программе и другие потоки работающие в параллель с нашим поиском победителя (и в частности запускать сам такой поиск победителя в независимых потоках). Правда для оформления этого кода в отдельные потоки - возможно потребуется избавиться от глобальных переменных и работать только через передаваемые в job параметры.
    Ответ написан
    Комментировать