Exception Chaining

Sebuah exception bisa menyebabkan exception lainnya. Python hanya support satu exception per satu waktu, untuk mengatasinya Python menyediakan chaining exception.

Dengan Chaining, kita bisa asosiasikan satu exception dengan exception lainnya.

Chaining ada dua macam, explicit dan implicit.

Implicit Chaining

Exception kedua terjadi saat memproses exception pertama, ditangani oleh Python secara otomatis.

Berikut demo program untuk implicit chaining, kita gunakan program sebelumnya dengan modifikasi menambahkan 2 bug.

import math
import sys

class TriangleError (Exception):
    def __init__ (self, text, sides):
        super().__init__(text)
        self._sides = tuple(sides)
    
    @property
    def sides(self):
        return self._sides
    
    def __str__(self):
        return "'{}' for sides {}".format(self.args[0], self._sides)

    def __repr__(self):
        return "TriangleError({!r}, {!r})".format(self.args[0], self._sides)


def luas_segitiga(a, b, c):
    sides = sorted((a, b, c))
    if sides[2] > sides [0] + sides [1]:
        raise TriangleError("Segitiga Error", sides)

    s = (a + b + c) / 2
    l = math.sqrt(s * (s-a) * (s-b) * (s-c))
    return l

def main():
    try:
        a = luas_segitiga(3, 4, 10)
        print(a)
    except TriangleError as e:
        print(e, file=sys.stdin)

PS F:\Project\pyErrHandling> python
Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from heron import *
>>> main()
Traceback (most recent call last):
  File "F:\Project\pyErrHandling\heron.py", line 31, in main
    a = luas_segitiga(3, 4, 10)
  File "F:\Project\pyErrHandling\heron.py", line 23, in luas_segitiga
    raise TriangleError("Segitiga Error", sides)
heron.TriangleError: 'Segitiga Error' for sides (3, 4, 10)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "F:\Project\pyErrHandling\heron.py", line 34, in main
    print(e, file=sys.stdin)
io.UnsupportedOperation: not writable

Perhatikan log diatas, terdapat error log “During handling of the above exception, another exception occured”.

Implicit chaining menyimpan exception pertama pada __context__ attribute. Lihat code dibawah yang untuk menunjukan exception terdapat pada __context__ attribute.

import math
import sys
import io

class TriangleError (Exception):
    def __init__ (self, text, sides):
        super().__init__(text)
        self._sides = tuple(sides)
    
    @property
    def sides(self):
        return self._sides
    
    def __str__(self):
        return "'{}' for sides {}".format(self.args[0], self._sides)

    def __repr__(self):
        return "TriangleError({!r}, {!r})".format(self.args[0], self._sides)


def luas_segitiga(a, b, c):
    sides = sorted((a, b, c))
    if sides[2] > sides [0] + sides [1]:
        raise TriangleError("Segitiga Error", sides)

    s = (a + b + c) / 2
    l = math.sqrt(s * (s-a) * (s-b) * (s-c))
    return l

def main():
    try:
        a = luas_segitiga(3, 4, 10)
        print(a)
    except TriangleError as e:
        try:
            print(e, file=sys.stdin)
        except io.UnsupportedOperation as f:
            print(e)
            print(f)
            print(f.__context__ is e)
>>> main()
'Segitiga Error' for sides (3, 4, 10)
not writable
True

Explicit Chaining

Secara eksplisit ditulis dalam program untuk meresponse terhadap exception yang terjadi saat memprose exception pertama.

Berikut program sederhana untuk menghitung kemiringan. Untuk chaining secara eksplisit, digunakan keyword from.

import math

class InclinationErr(Exception):
    pass

def inclination(dx, dy):
    try:
        return math.degrees(math.atan(dy/dx))
    except ZeroDivisionError as e:
        raise InclinationErr("Tidak ada kemiringan") from e
>>> from inclination import *
>>> inclination(0, 2)
Traceback (most recent call last):
  File "F:\Project\pyErrHandling\inclination.py", line 8, in inclination
    return math.degrees(math.atan(dy/dx))
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "F:\Project\pyErrHandling\inclination.py", line 10, in inclination
    raise InclinationErr("Tidak ada kemiringan") from e
inclination.InclinationErr: Tidak ada kemiringan
>>>

log diatas menunjukan exception message berbeda dengan implicit chaining, yaitu “The above exception was the direct cause of the following exception:”

Explicit chaining menyimpan exception pertama pada __cause__ attribute.

>>> try:
...     inclination(0,5)
... except InclinationErr as e:
...     print(e)
...     print(e.__cause__)
... 
Tidak ada kemiringan
division by zero
Sharing is caring:

Leave a Comment