Как узнать, что параллельный процесс не завис в Python?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как узнать, что параллельный процесс не завис в 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
Обнаружение зависаний — это не одноразовая проверка, а непрерывный процесс мониторинга состояния приложения.