← Назад к вопросам

Как узнать, что параллельный процесс не завис в Python?

3.0 Senior🔥 81 комментариев
#Python Core#Асинхронность и многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как узнать, что параллельный процесс не завис в Python?

Визуализирование состояния параллельных процессов и своевременное обнаружение зависаний — критична задача при разработке многопроцессных приложений на Python.

1. Использование is_alive()

Это базовый и самый простой способ проверки статуса процесса:

from multiprocessing import Process
import time

def worker():
    time.sleep(2)
    print("Работа завершена")

p = Process(target=worker)
p.start()

# Проверяем, работает ли процесс
if p.is_alive():
    print("Процесс ещё выполняется")
else:
    print("Процесс завершился")

Метод is_alive() возвращает True если процесс активен, False если завершился или не был запущен.

2. Timeout при join()

Используйте параметр timeout в методе join() для ограничения времени ожидания:

from multiprocessing import Process
import time

def slow_worker():
    time.sleep(10)

p = Process(target=slow_worker)
p.start()

# Ждёмprocess максимум 2 секунды
p.join(timeout=2)

if p.is_alive():
    print("ВНИМАНИЕ: Процесс завис!")
    p.terminate()  # или p.kill()
else:
    print("Процесс завершился нормально")

Это позволяет обнаружить зависания и принять меры (terminate/kill).

3. Проверка exitcode

После завершения процесса можно проверить код выхода:

from multiprocessing import Process

def faulty_worker():
    raise Exception("Ошибка в процессе")

p = Process(target=faulty_worker)
p.start()
p.join()

if p.exitcode is None:
    print("Процесс ещё работает")
elif p.exitcode == 0:
    print("Процесс завершился успешно")
elif p.exitcode < 0:
    print(f"Процесс убит сигналом {-p.exitcode}")
else:
    print(f"Процесс завершился с ошибкой {p.exitcode}")

4. Heartbeat паттерн с очередями

Для более сложных случаев используйте очереди для периодических сигналов:

from multiprocessing import Process, Queue
import time
import threading

def worker_with_heartbeat(queue):
    while True:
        queue.put("alive")
        time.sleep(1)
        # выполняем работу

def monitor(queue, timeout=3):
    last_heartbeat = time.time()
    while True:
        try:
            msg = queue.get(timeout=timeout)
            last_heartbeat = time.time()
            print(f"Получен сигнал: {msg}")
        except:
            if time.time() - last_heartbeat > timeout:
                print("КРИТИЧЕСКАЯ ОШИБКА: Процесс завис!")
                break

p = Process(target=worker_with_heartbeat, args=(queue,))
queue = Queue()
p.start()
monitor(queue)

5. Watchdog с threading

Для долгоживущих приложений создайте отдельный watchdog поток:

from multiprocessing import Process
import time
import threading

def watchdog(process, timeout=5):
    start_time = time.time()
    while process.is_alive():
        elapsed = time.time() - start_time
        if elapsed > timeout:
            print("Процесс превысил лимит времени!")
            process.terminate()
            process.join(timeout=2)
            if process.is_alive():
                process.kill()
            return False
        time.sleep(0.5)
    return True

def worker():
    time.sleep(10)

p = Process(target=worker)
p.start()
watchdog(p, timeout=3)

6. Мониторинг с использованием psutil

Для профессионального мониторинга используйте внешнюю библиотеку:

import psutil
from multiprocessing import Process

def worker():
    pass

p = Process(target=worker)
p.start()

# Получаем информацию о процессе ОС
proc = psutil.Process(p.pid)

print(f"CPU: {proc.cpu_percent()}%")
print(f"Memory: {proc.memory_info().rss / 1024 / 1024}MB")
print(f"Status: {proc.status()}")

if proc.status() == psutil.STATUS_ZOMBIE:
    print("Процесс в состоянии зомби!")

Лучшие практики

  • Всегда используйте timeout при join() в production
  • Логируйте зависания для отладки
  • Реализуйте graceful shutdown вместо kill()
  • Мониторьте ресурсы (CPU, память) для раннего обнаружения проблем
  • Используйте контексты if __name__ == "__main__" на Windows

Обнаружение зависаний — это не одноразовая проверка, а непрерывный процесс мониторинга состояния приложения.

Как узнать, что параллельный процесс не завис в Python? | PrepBro