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?
logging
modü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 |