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
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ı:
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ı
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ı
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ı
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
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
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
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ı
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
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
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?
loggingmodülü vemultiprocessing.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öntem | Avantajlar | Dezavantajlar |
|---|---|---|
| subprocess.run() | Basit komut çalıştırma | Limitli kontrol |
| multiprocessing.Pool | Kaynak verimliliği | Karmaşık hata yönetimi |
| ProcessPoolExecutor | Future tabanlı kontrol | Python 3.2+ gerektirir |