Giriş: ChildProcessError Nedir?

ChildProcessError, Python'da bir alt işlem (child process) ile ilgili işlemler sırasında ortaya çıkan bir istisna (exception) türüdür. Bu hata, genellikle:

✔ Alt işlem başlatma/iletişim sorunlarında
✔ Process havuzu (pool) kullanımında
✔ Çoklu işlem (multiprocessing) senaryolarında

görülür. Bu makalede, ChildProcessError'ın nedenlerini, çözüm yöntemlerini ve en iyi uygulamaları detaylıca inceleyeceğiz.


1. ChildProcessError Ne Zaman Oluşur?

ChildProcessError, bir ana işlemin (parent process) alt işlemle (child process) iletişim kuramadığı veya alt işlemin beklenmedik şekilde sonlandığı durumlarda fırlatılır.

Örnek: Temel ChildProcessError Senaryosu

python
Copy
Download
import subprocess

try:
    # Var olmayan bir komut çalıştırma
    subprocess.run(['varolmayan_komut'], check=True)
except subprocess.CalledProcessError as e:
    print(f"Komut hatası: {e}")
except ChildProcessError as e:
    print(f"Alt işlem hatası: {e}")

Çıktı:

text
Copy
Download
FileNotFoundError: [Errno 2] No such file or directory: 'varolmayan_komut'

Not: Python'da ChildProcessError genellikle daha spesifik hataların (subprocess.CalledProcessError gibi) altında kullanılır.


2. ChildProcessError'ın Yaygın Nedenleri

a) Alt İşlemin Beklenmedik Şekilde Sonlanması

python
Copy
Download
import multiprocessing

def worker():
    raise RuntimeError("İşlem hatası")

try:
    p = multiprocessing.Process(target=worker)
    p.start()
    p.join()
except ChildProcessError as e:
    print(f"Alt işlem çöktü: {e}")

b) Process Pool'da İşlem Hatası

python
Copy
Download
from concurrent.futures import ProcessPoolExecutor

def task(n):
    if n == 3:
        raise ValueError("Geçersiz değer")
    return n * n

with ProcessPoolExecutor() as executor:
    try:
        results = list(executor.map(task, [1, 2, 3, 4]))
    except ChildProcessError as e:
        print(f"Process havuzu hatası: {e}")

c) İşletim Sistemi Kaynak Kısıtlamaları

python
Copy
Download
import os
import signal

def handler(signum, frame):
    raise ChildProcessError("Sinyal ile kesildi")

signal.signal(signal.SIGCHLD, handler)
os.kill(os.getpid(), signal.SIGCHLD)  # Kendi kendine sinyal gönder

3. ChildProcessError Nasıl Çözülür?

a) Alt İşlem Çıkış Kodlarını Kontrol Etme

python
Copy
Download
import subprocess

result = subprocess.run(['ls', '/var'], capture_output=True)
if result.returncode != 0:
    print(f"Alt işlem başarısız: {result.stderr.decode()}")

b) Process Pool'da Hata Yönetimi

python
Copy
Download
from concurrent.futures import ProcessPoolExecutor, as_completed

def task(n):
    if n == 3:
        raise ValueError("Özel hata")
    return n * n

with ProcessPoolExecutor() as executor:
    futures = [executor.submit(task, i) for i in range(5)]
    for future in as_completed(futures):
        try:
            print(future.result())
        except ValueError as e:
            print(f"Hata yakalandı: {e}")

c) Çoklu İşlemlerde Kaynak Temizleme

python
Copy
Download
import multiprocessing
import time

def worker():
    time.sleep(2)
    print("İşlem tamam")

procs = []
for _ in range(3):
    p = multiprocessing.Process(target=worker)
    procs.append(p)
    p.start()

try:
    for p in procs:
        p.join()
except ChildProcessError:
    print("Alt işlem hatası")
finally:
    for p in procs:
        if p.is_alive():
            p.terminate()

4. Gerçek Dünya Senaryoları ve Çözümleri

a) Güvenli Process Pool Kullanımı

python
Copy
Download
from concurrent.futures import ProcessPoolExecutor
import random

def process_data(data):
    if random.random() < 0.2:  # %20 hata olasılığı
        raise ValueError("Rastgele hata")
    return data * 2

def safe_process(data_list):
    with ProcessPoolExecutor(max_workers=4) as executor:
        futures = {executor.submit(process_data, data): data 
                   for data in data_list}
        
        results = {}
        for future in concurrent.futures.as_completed(futures):
            data = futures[future]
            try:
                results[data] = future.result()
            except ValueError as e:
                print(f"{data} işlenirken hata: {e}")
                results[data] = None
    return results

b) Dağıtık İşlemlerde Hata Yönetimi

python
Copy
Download
import multiprocessing
import sys

def distributed_task(task_id):
    try:
        # Karmaşık hesaplama
        if task_id % 5 == 0:
            raise RuntimeError(f"Task {task_id} hatası")
        return task_id ** 2
    except Exception as e:
        # Hata bilgisini ana işleme ilet
        raise ChildProcessError(f"Alt işlem {task_id} çöktü: {e}")

def run_distributed_tasks():
    with multiprocessing.Pool(4) as pool:
        try:
            results = pool.map(distributed_task, range(20))
        except ChildProcessError as e:
            print(f"Dağıtık işlem hatası: {e}")
            sys.exit(1)
        return results

5. Performans ve Güvenlik İpuçları

✔ Alt işlem sayısını CPU çekirdek sayısıyla sınırlayın
✔ Process Pool'da max_workers parametresini optimize edin
✔ Kaynak sızıntılarını önlemek için with deyimini kullanın
✔ Alt işlemlerde oluşan hataları mutlaka loglayın

Örnek: Loglama ile Güçlendirilmiş İşlem Yönetimi

python
Copy
Download
import logging
import multiprocessing

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def worker_process(x):
    try:
        if x == 0:
            raise ValueError("Sıfıra bölme girişimi")
        return 100 / x
    except Exception as e:
        logging.error(f"İşlem {x} hatası: {e}")
        raise ChildProcessError(f"Worker hatası: {e}")

def managed_process():
    with multiprocessing.Pool(2) as pool:
        try:
            results = pool.map(worker_process, [0, 1, 2, 3])
            logging.info(f"Sonuçlar: {results}")
        except ChildProcessError as e:
            logging.critical(f"İşlem havuzu hatası: {e}")

Sonuç

✅ ChildProcessError, alt işlemlerdeki beklenmedik hataları yönetir
✅ Process Pool ve multiprocessing'te doğru hata yönetimi kritiktir
✅ Kaynak sızıntılarını önlemek için with deyimi kullanılmalıdır
✅ Üretim ortamlarında hataları mutlaka loglayın


Sık Sorulan Sorular (SSS)

❓ ChildProcessError ile CalledProcessError arasındaki fark nedir?

  • CalledProcessError: subprocess.run() ile çalıştırılan komutların hataları

  • ChildProcessError: Genel alt işlem hataları

❓ Alt işlemlerdeki hataları nasıl debug ederim?

  • logging modülü ve multiprocessing.log_to_stderr() kullanın

❓ Windows'ta ChildProcessError farklı mıdır?

  • Temel davranış aynıdır, ancak işletim sistemi özel hataları farklı olabilir


Özet Tablo

YöntemAvantajlarDezavantajlar
subprocess.run()Basit komut çalıştırmaLimitli kontrol
multiprocessing.PoolKaynak verimliliğiKarmaşık hata yönetimi
ProcessPoolExecutorFuture tabanlı kontrolPython 3.2+ gerektirir