34. Xử lý ngoại lệ

Xử lý ngoại lệ là hệ thống luồng điều khiển mà CPython sử dụng khi một thao tác không thể hoàn thành bình thường. Nó bao gồm rõ ràngraisecâu lệnh, hoạt động không thành công, nhập không thành công, cuộc gọi không thành công, chấm dứt trình tạo, dọn dẹp trình quản lý bối cảnh, xây dựng truy nguyên và truyền bá qua khung.

Ở cấp độ nguồn, các ngoại lệ trông như thế này:python id="cq34p8" try: value = risky() except ValueError: value = 0 Khi chạy, CPython phải:```text id="o1a48o" execute the protected bytecode range detect failure record the active exception find a matching handler restore the frame stack to a valid state jump to handler bytecode run cleanup code propagate if no handler matches


## 34.1 Ngoại lệ là gì

Ngoi l là mt đối tượng đại din cho lung điu khin bt thường.

Hu hết các trường hp ngoi l là các th hin ca các lp bt ngun t`BaseException`.

```python id="m6c3g8"
raise ValueError("bad input")
```Điu này to ra hoc s dng mt đối tượng ngoi l và chuyn vic thc thi ra khi đường dn thông thường hin ti.

H thng phân cp ngoi l bt đầu bng:```text id="axuv64"
BaseException
    SystemExit
    KeyboardInterrupt
    GeneratorExit
    Exception
        ValueError
        TypeError
        RuntimeError
        OSError
        ...
```Hu hết các trường hp ngoi l  cp độ ng dng đều xut phát t`Exception`, không trc tiếp t`BaseException`.

Điu này quan trng bi vì:```python id="yj96ne"
except Exception:
    ...
```thường không bt được`KeyboardInterrupt`, `SystemExit`, hoc`GeneratorExit`.

## 34.2 Trả về bình thường và Trả về ngoại lệ

Mt hàm Python có th thoát theo hai cách chính:```text id="ea7eqq"
normal return
exception propagation
```Li nhun bình thường:```python id="0q9s27"
def f():
    return 42
```V mt khái nim:```text id="g7wklr"
LOAD_CONST 42
RETURN_VALUE
```Thoát ngoi l:```python id="h98nnl"
def f():
    raise ValueError("bad")
```V mt khái nim:```text id="zpp0ri"
create ValueError object
set exception state
unwind frame
```Người gi s nhn được:```text id="szzwfe"
a returned PyObject pointer
or an error indication with exception state set
``` cp độ API C, nhiu hàm tuân theo hình dng này:```c id="b99eij"
PyObject *result = some_operation();
if (result == NULL) {
    /* exception is set */
    return NULL;
}
```các`NULL`li tín hiu tr v. Ngoi l thc tế được lưu tr  trng thái lung trình thông dch.

## 34.3 Ngoại lệ dưới dạng luồng điều khiển

Các ngoi l được s dng cho các li cũng như cho lung điu khin có cu trúc.

Ví d:```text id="kfz3yw"
StopIteration ends iteration
StopAsyncIteration ends async iteration
GeneratorExit closes generators
KeyboardInterrupt interrupts execution
SystemExit requests interpreter exit
ImportError reports import failure
AttributeError reports missing attributes
```các`for`vòng lp ph thuc vào`StopIteration`ni b:```python id="79e3jp"
for x in xs:
    body(x)
```V mt khái nim:```text id="9mx6jc"
iterator = iter(xs)

while true:
    try:
        x = next(iterator)
    except StopIteration:
        break
    body(x)
```Vì vy, các ngoi l là mt phn ca giao thc thông dch thông thường.

## 34.4 Đưa ra một ngoại lệ

A`raise`câu lnh chuyn quyn kim soát ti b máy ngoi l.```python id="ctu8dt"
raise ValueError("bad")
```Mã byte gn như thc hin:```text id="h4k87k"
load ValueError
load "bad"
call ValueError("bad")
raise resulting exception
```Vic tăng lương có th s dng:```python id="zewoqj"
raise SomeError
raise SomeError("message")
raise existing_exception
raise
```Mt trn`raise`ch hp l khi x lý mt ngoi l đang hot động:```python id="3qrtpf"
try:
    risky()
except ValueError:
    raise
```Nó làm tăng li ngoi l hin đang được x lý.

## 34.5 Các lớp và trường hợp ngoại lệ

Python cho phép bn đưa ra mt lp ngoi l hoc mt th hin ngoi l.```python id="q6npyl"
raise ValueError
```CPython bình thường hóa điu này thành mt phiên bn khi cn thiết.```python id="z91m3v"
raise ValueError("bad")
```đã cung cp mt ví d.

Trong ni b, vic x lý ngoi l thường cn trng thái ba hoc tương đương được chun hóa:```text id="dk5r5k"
exception type
exception value
traceback
```CPython hin đại th hin và qun lý trng thái này thông qua các cu trúc ngoi l bên trong, nhưng mô hình khái nim vn hu ích.

## 34.6 Truy nguyên

Truy nguyên ghi li nơi ngoi l đã di chuyn.

Ví d:```python id="1mo1jg"
def a():
    b()

def b():
    c()

def c():
    1 / 0

a()
```Truy nguyên cha các mc nhp cho các khung hot động:```text id="83c801"
a
b
c
ZeroDivisionError
```Mi mc truy nguyên đề cp đến:```text id="qjfi2r"
frame
code object
instruction position
source line information
next traceback entry
```Truy nguyên là d liu thi gian chy có cu trúc, không ch là văn bn được định dng.

Đây là lý do ti sao các ngoi l có th gi li các biến cc b mt cách gián tiếp:```text id="yoeiyb"
exception
    traceback
        frame
            locals
```## 34.7 Giải phóng khung hình

Khi mt ngoi l không được x lý trong khung hin ti, CPython s m khung và truyn ngoi l đó cho người gi.

Ví d:```python id="s11efk"
def f():
    raise ValueError

def g():
    f()

def h():
    g()
```Nếu không có trình x lý nào tn ti:```text id="eeh2v4"
frame f raises
frame f unwinds
frame g receives exception
frame g unwinds
frame h receives exception
frame h unwinds
top level prints traceback
```Nếu mt trình x lý tn ti trong`g`, s lan truyn dng li  đó:```python id="5x9m87"
def g():
    try:
        f()
    except ValueError:
        return 0
```Trình x lý ngoi l tr thành mc tiêu lung điu khin mi.

## 34.8 Bảng ngoại lệ

CPython hin đại s dng các bng ngoi l được liên kết vi các đối tượng mã để mô t các vùng và trình x lý được bo v.

MT`try`tuyên b:```python id="pl5k0d"
try:
    risky()
except ValueError:
    recover()
```biên dch thành:```text id="p4ajhn"
bytecode for risky()
bytecode for handler
exception table mapping protected range to handler
```Bng ngoi l ghi li các thông tin như:```text id="ca8e5f"
protected bytecode start
protected bytecode end
handler target
stack depth to restore
handler kind
```Khi mt ngoi l xy ra, trình thông dch s dng v trí lnh hin ti để tìm kiếm trình x lý trong bng.

Điu này tránh vic duy trì mt s máy móc ngăn xếp khi cũ hơn để thc thi bình thường và cho phép các vùng ngoi l có chi phí bng 0 tránh được chi phí chung khi không có ngoi l nào xy ra.

## 34.9 Khôi phục ngăn xếp

Mt ngoi l có th xy ra khi các giá tr tm thi nm trên ngăn xếp khung.

Ví d:```python id="iz2gr7"
x = f(g(), h())
```Nếu như`h()`tăng lên, ngăn xếp có th cha:```text id="q5o3qr"
f
result_of_g
```Cuc gi đến`f`không bao gi xy ra. CPython phi gii phóng các tham chiếu tm thi và khôi phc ngăn xếp v độ sâu mà trình x lý ngoi l mong đợi.

Siêu d liu bng ngoi l cho trình thông dch biết độ sâu ngăn xếp cn khôi phc trước khi nhp trình x lý.

Điu này là cn thiết cho s đúng đắn. Trình x lý phi bt đầu vi hình dng ngăn xếp đã biết.

## 34.10 So khớp một ngoại lệ

Mt`except`mnh đề kim tra xem ngoi l hot động có khp vi mt loi hoc b loi hay không.```python id="ofe6wa"
try:
    risky()
except ValueError:
    handle()
```Trình x lý khp nếu ngoi l là mt th hin ca`ValueError`hoc mt lp con.

So khp b d liu:```python id="3jtudw"
except (ValueError, TypeError):
    handle()
```phù hp vi mt trong hai loi.

Hot động so khp s dng các mi quan h lp ngoi l. Nó không phi là mt so sánh chui.

## 34.11 Lệnh xử lý

Trình x lý được kim tra theo th t ngun.```python id="dxve0m"
try:
    risky()
except Exception:
    handle_general()
except ValueError:
    handle_value()
```các`ValueError`trình x lý không th truy cp được vì`ValueError`là mt lp con ca`Exception`.

Th t đúng đặt trình x lý c th lên hàng đầu:```python id="6s99w7"
try:
    risky()
except ValueError:
    handle_value()
except Exception:
    handle_general()
```Trình biên dch thường không t chi các trình x lý ngoi l không th truy cp được. Thi gian chy tuân theo th t đã cho.

## 34.12 Ràng buộc biến ngoại lệ

Mt`except ... as name`mnh đề liên kết đối tượng ngoi l.```python id="gn531x"
try:
    risky()
except ValueError as exc:
    print(exc)
```Bên trong trình x lý:```text id="1csxmt"
exc -> exception instance
```Sau trình x lý, Python xóa ràng buc này để gim các chu k tham chiếu liên quan đến truy nguyên.

V mt khái nim:```python id="lqlby5"
except ValueError as exc:
    ...
finally:
    del exc
```Điu này ngăn cn mt chu k lưu gi chung:```text id="bi9brc"
exception
    traceback
        frame
            locals
                exception
```## 34.13 Trần`except`Một người xử lý trần sẽ nắm bắt được hầu hết mọi thứ:```python id="cfaisv"
try:
    risky()
except:
    handle()
```Nó bt các ngoi l bt ngun t`BaseException`, bao gm`KeyboardInterrupt`Và`SystemExit`.

Điu này thường quá rng.

Thích hơn:```python id="8l0yll"
except Exception:
    handle()
```khi x lý các li ng dng thông thường.

Mt trn`except`vn có th phù hp khi mã phi thc hin dn dp và sau đó khi động li:```python id="2sx6wj"
try:
    risky()
except:
    cleanup()
    raise
```## 34,14`else`Khối

A`try`tuyên b có th có mt`else`khi.```python id="ne9sbh"
try:
    value = parse()
except ValueError:
    value = default
else:
    use(value)
```các`else`khi ch chy nếu`try`khi hoàn thành mà không có ngoi l.

Nó không chy nếu:```text id="tmvff1"
the try block raises
the try block returns
the try block breaks
the try block continues
``` cp độ mã byte, đây là lung điu khin nhánh thông thường xung quanh khi x lý.

## 34,15`finally`Khối

A`finally`khi chy khi điu khin ri khi`try`khi.```python id="sk93di"
try:
    risky()
finally:
    cleanup()
```Quá trình dn dp din ra cho:```text id="6kjx4b"
normal fallthrough
return
exception
break
continue
```Ví d:```python id="pkbx1h"
def f():
    try:
        return 1
    finally:
        print("cleanup")
```Vic tr li đang ch x lý trong khi`finally`cơ th chy.

Nếu`finally`body tăng lên, nó thay thế phn tr v đang ch x lý:```python id="a8odfm"
def f():
    try:
        return 1
    finally:
        raise RuntimeError("cleanup failed")
```Chc năng này tăng`RuntimeError`thay vì quay li`1`.

## 34,16`return`Bên trong`finally`MỘT`return`bên trong`finally`ghi đè các ngoại lệ hoặc trả về trước đó.```python id="lip58q"
def f():
    try:
        raise ValueError("bad")
    finally:
        return 10
```Điu này tr v`10`. các`ValueError`b đàn áp.

Hành vi này là hp pháp nhưng nguy him. Nó có th che giu li.

Trong thi gian chy,`finally`khi điu khin đường thoát cui cùng. Nếu nó tr v, kết qu tr v đó s tr thành kết qu ca hàm.

## 34.17 Trình quản lý bối cảnh và ngoại lệ

A`with`tuyên b được xây dng trên x lý ngoi l.```python id="0710p4"
with manager as value:
    body(value)
```V mt khái nim:```python id="nd0spg"
mgr = manager
exit = mgr.__exit__
value = mgr.__enter__()
try:
    body(value)
except BaseException as exc:
    suppress = exit(type(exc), exc, exc.__traceback__)
    if not suppress:
        raise
else:
    exit(None, None, None)
```Nếu như`__exit__`tr v giá tr thc, ngoi l b loi b.

Đây là cách người qun lý bi cnh có th trin khai khôi phc giao dch, đóng tp, khóa, trng thái tm thi và dn dp tài nguyên.

## 34,18`with`Mã byte

A`with`câu lnh biên dch thành mã byte:```text id="x3hc42"
loads the context manager
calls __enter__
stores the as-target
executes the body
calls __exit__ on normal exit
calls __exit__ on exceptional exit
suppresses or reraises based on return value
```Trình thông dch phi gi đủ trng thái để gi`__exit__`ngay c khi cơ th tăng lên.

Điu này làm cho`with`mt dng có cu trúc ca`try/finally`cng vi vic ngăn chn ngoi l.

## 34.19 Ngoại lệ có chuỗi

Python ghi li bi cnh ngoi l.

Ví d:```python id="vpsoic"
try:
    int("x")
except ValueError:
    raise RuntimeError("parse failed")
```các`RuntimeError`có bi cnh tr đến bn gc`ValueError`.

Đầu ra Traceback có ni dung như sau:```text id="9g0agc"
During handling of the above exception, another exception occurred
```S dng chui rõ ràng`from`:

```python id="iw2vuv"
raise RuntimeError("parse failed") from exc
```Ngăn chn vic s dng ng cnh:```python id="gg994p"
raise RuntimeError("parse failed") from None
```Các đối tượng ngoi l có các trường như:```text id="pqfm3s"
__context__
__cause__
__suppress_context__
__traceback__
```## 34.20 Trạng thái ngoại lệ trong Trạng thái luồng

Ngoi l hot động được lưu tr  trng thái lung trình thông dch.

Đây là lý do ti sao hàm C có th báo hiu li bng cách tr v`NULL`trong khi để li ngoi l  nơi khác.

V mt khái nim:```text id="y794el"
thread state
    current exception
    handled exception stack
```Khi trình tr giúp C b li:```c id="gctod1"
PyErr_SetString(PyExc_ValueError, "bad");
return NULL;
```Người gi kim tra giá tr tr v và biết ngoi l được đặt.

Vòng đánh giá sau đó s truyn bá hoc x lý nó.

## 34.21 Quy ước lỗi API C

Các hàm API CPython C thường tuân theo mt trong mt s quy ước v li.

Các hàm tr v con tr:```c id="f6xl1n"
PyObject *obj = PyLong_FromString(text, NULL, 10);
if (obj == NULL) {
    return NULL;
}
```Hàm tr v s nguyên:```c id="tj37v0"
int rc = PyObject_SetAttrString(obj, "x", value);
if (rc < 0) {
    return NULL;
}
```Kim tra ging Boolean có th tr li`1`, `0`, hoc`-1`:

```c id="71hl88"
int ok = PyObject_IsTrue(obj);
if (ok < 0) {
    return NULL;
}
```Kết qu li và trng thái ngoi l phi ging nhau. Tr li mã li mà không đặt ngoi l thường là li.

## 34,22 Tăng từ C

Mã C tăng ngoi l Python bng cách đặt trng thái li.

Ví d:```c id="c8dwxx"
PyErr_SetString(PyExc_TypeError, "expected integer");
return NULL;
```Đối vi tin nhn được định dng:```c id="npt9uu"
PyErr_Format(PyExc_ValueError, "bad value: %d", value);
return NULL;
```Để truyn bá mt ngoi l hin có, mã C tr v trng đim li mà không ghi đè ngoi l đó.

Mu này cho phép li di chuyn qua nhiu hàm C cho đến khi vòng đánh giá tìm thy trình x lý Python hoc thoát lên cp cao nht.

## 34.23 Xóa ngoại lệ

Đôi khi mã C c ý x lý mt ngoi l và xóa nó.

V mt khái nim:```c id="44mmje"
PyObject *value = PyObject_GetAttrString(obj, "optional");
if (value == NULL) {
    if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
        PyErr_Clear();
        value = default_value;
    }
    else {
        return NULL;
    }
}
```Xóa ngoi l sai có th che giu các li thc s.

Mã Python có mu tương t:```python id="rcjz53"
try:
    value = obj.optional
except AttributeError:
    value = default
```Nguyên tc chính là ch bt ngoi l mà bn định x lý.

## 34.24 Ngoại lệ trong quá trình xử lý ngoại lệ

Trình x lý có th đưa ra mt ngoi l khác.```python id="gc39fq"
try:
    risky()
except ValueError:
    recover_badly()
```Nếu như`recover_badly()`tăng lên, ngoi l mi s thay thế kết qu bình thường ca trình x lý trong khi vn gi nguyên bi cnh v ngoi l ban đầu.

MT`finally`khi cũng có th tăng lên trong quá trình dn dp.

CPython phi bo toàn đủ trng thái để xây dng chui truy nguyên hu ích.

## 34.25 Ngoại lệ và Trình tạo

Máy phát đin s dng ngoi l để kim soát.

Mt máy phát đin kết thúc bng cách nâng cao`StopIteration`ni b cho người gi.```python id="dz6ljh"
def gen():
    yield 1

g = gen()
next(g)
next(g)
```th hai`next(g)`tăng lên`StopIteration`.

MT`return value`bên trong mt máy phát đin tr thành giá tr gn lin vi`StopIteration`.

```python id="r2gskh"
def gen():
    return 42
    yield

g = gen()
try:
    next(g)
except StopIteration as exc:
    print(exc.value)
```Đầu ra là:```text id="4y674v"
42
```S dng hoàn thin máy phát đin`GeneratorExit`.

## 34.26 PEP 479 và Máy phát điện

A`StopIteration`vô tình được nâng lên bên trong thân máy phát đin được chuyn thành`RuntimeError`.

Ví d:```python id="muj1jf"
def gen():
    raise StopIteration
    yield
```Điu này tránh được nhng li nh khi vô tình`StopIteration`âm thm chm dt máy phát đin.

Giao thc máy phát đin vn s dng`StopIteration` ranh gii. Vic chuyn đổi áp dng bên trong vic thc thi trình to.

## 34.27 Ngoại lệ và Coroutine

Coroutine cũng s dng các đường dn ngoi l để hy và x lý li.

Mt coroutine được ch đợi có th hoàn thành bình thường:```text id="tp92nc"
return value
```hoc tht bi:```text id="cvojm0"
raise exception
```Vic hy b thường được th hin bng mt ngoi l được đưa vào quá trình thc thi coroutine.

Khung coroutine tiếp tc vi mt ngoi l thay vì giá tr bình thường.

Điu này có nghĩa là các khung không đồng b ph thuc sâu sc vào mô hình tm dng, ni li và truyn ngoi l khung ca CPython.

## 34.28 Nhóm ngoại lệ

Python hin đại bao gm các nhóm ngoi l để biu din nhiu ngoi l cùng nhau.```python id="0cenmj"
raise ExceptionGroup("many", [ValueError("a"), TypeError("b")])
```Chúng được x lý bng`except*`:

```python id="ihrw3w"
try:
    raise ExceptionGroup("many", [ValueError("a"), TypeError("b")])
except* ValueError as group:
    handle_values(group)
except* TypeError as group:
    handle_types(group)
```Điu này quan trng đối vi các chương trình đồng thi trong đó nhiu tác v có th b li cùng mt lúc.

Trình thông dch phi phân chia và khp các nhóm ngoi l trên`except*`người x lý.

## 34,29`except*`

`except*`khác vi bình thường`except`.

Bình thường`except`chn mt trình x lý cho mt ngoi l đang hot động.`except*`có th chia mt nhóm ngoi l và định tuyến các ngoi l ph khác nhau cho các trình x lý khác nhau.

V mt khái nim:```text id="7m7ae6"
ExceptionGroup(ValueError, TypeError)
    except* ValueError receives ValueError subgroup
    except* TypeError receives TypeError subgroup
```Bt k nhóm con nào chưa tng có s tiếp tc lan truyn.

Điu này b sung kh năng x lý nhiu li có cu trúc mà không loi b các danh tính ngoi l riêng l.

## 34.30 Lưu giữ dấu vết

Du vết giúp gi cho khung hình luôn sng động.

Ví d:```python id="7vw5yb"
saved = None

def f():
    big = bytearray(100_000_000)
    raise RuntimeError

try:
    f()
except RuntimeError as exc:
    saved = exc
```Ngoi l đã lưu có th gi li du vết ca nó. Traceback gi li khung. Khung gi li biến cc b`big`.

Chui lưu gi:```text id="9fqt5r"
saved exception
    traceback
        frame
            locals
                big bytearray
```Đây là lý do ti sao các ngoi l tn ti lâu dài có th gi được b nh đáng k.

## 34.31 Làm sạch dấu vết

Bn có th tránh vic lưu gi bng cách không lưu tr các ngoi l lâu hơn mc cn thiết hoc bng cách xóa các tham chiếu truy nguyên.```python id="tb2iqr"
try:
    f()
except RuntimeError as exc:
    handle(exc)
    exc = None
```Để dn dp rõ ràng:```python id="smrtfq"
exc.__traceback__ = None
```Hãy s dng tính năng này mt cách cn thn vì vic truy nguyên rt hu ích cho vic g li.

Nguyên tc chung là: lưu tr ngoi l lưu tr bi cnh.

## 34,32`finally`và dọn dẹp tham chiếu`finally`thường được sử dụng để giải phóng tài nguyên.```python id="iibrsm"
resource = acquire()
try:
    use(resource)
finally:
    resource.close()
```Hình thc ưa thích để qun lý tài nguyên thường là trình qun lý bi cnh:```python id="tfg64f"
with acquire() as resource:
    use(resource)
```C hai hình thc đều ph thuc vào máy móc x lý ngoi l để đảm bo quá trình dn dp din ra khi điu khin ri khi khi được bo v.

## 34.33 Ngoại lệ và`__del__`Các ngoại lệ được nêu ra trong bộ hoàn thiện đối tượng được xử lý đặc biệt.```python id="6vbsh5"
class C:
    def __del__(self):
        raise RuntimeError("bad finalizer")
```Mt ngoi l t`__del__`không th truyn bình thường ti mã người dùng ti thi đim xy ra vic thu gom rác. CPython báo cáo nó thông qua máy móc ngoi l không th x lý được.

Đây là lý do ti sao nhng người quyết toán nên tránh raise.

## 34.34 Ngoại lệ không thể xử lý được

Mt s trường hp ngoi l xy ra khi vic truyn bá bình thường là không th.

Ví d:```text id="ydy6r1"
__del__ finalizers
weakref callbacks
some cleanup hooks
background finalization contexts
```CPython báo cáo nhng điu này thông qua vic x lý ngoi l không th x lý được, có sn thông qua`sys.unraisablehook`.

Điu này bo tn thông tin chn đoán mà không phá v các bi cnh lung điu khin không th thc hin được.

## 34,35 Ngoại lệ và nhập khẩu

Li nhp khu s dng ngoi l.```python id="54d93q"
import missing_module
```tăng lên`ModuleNotFoundError`.

Quá trình nhp có th không thành công  mt s giai đon:```text id="0yjm9i"
module search
loader creation
source reading
bytecode loading
module execution
submodule import
package initialization
```Nếu quá trình thc thi mô-đun tăng lên thì quá trình nhp không thành công vi ngoi l đó.

Vì vic nhp mô-đun chy mã cp cao nht ca nó nên các ngoi l tùy ý có th phát sinh trong quá trình nhp.

## 34.36 Ngoại lệ và tra cứu thuộc tính

Thiếu tăng tra cu thuc tính`AttributeError`.

```python id="qcd62q"
obj.missing
```Nhưng tra cu tùy chnh có th nâng cao bt c điu gì:```python id="otwoa7"
class C:
    @property
    def x(self):
        raise RuntimeError("failed")
```Điu này quan trng đối vi`getattr`, `hasattr`và các khung động.`hasattr`đánh bt`AttributeError`, không phi là ngoi l tùy ý.

## 34.37 Ngoại lệ và lặp lại

S dng lp li`StopIteration`.

Tương đương th công:```python id="0pw412"
it = iter(xs)

while True:
    try:
        x = next(it)
    except StopIteration:
        break
    body(x)
``` cp độ bytecode, các lnh vòng lp nhn biết s cn kit ca vòng lp và phân nhánh ra khi vòng lp.

Đây là mt đường dn ngoi l bình thường, được mong đợi.

## 34.38 Ngoại lệ và So khớp mẫu

Vic so khp mu có th s dng li trong ni b mà không để l ra các ngoi l đối vi các kết qu không khp thông thường.```python id="vlqdr7"
match value:
    case {"x": x}:
        ...
    case _:
        ...
```Công c phù hp phi phân bit:```text id="b58239"
pattern does not match
operation raises a real exception
```Mt mu không thành công s chuyn sang trường hp tiếp theo. Mt ngoi l thc s nên được tuyên truyn.

## 34.39 Ngoại lệ và hướng dẫn mã byte

Nhiu hướng dn mã byte có th tăng lên.

Ví d:

| Loi hướng dn | Có th tht bi |
|---|---|
|`LOAD_GLOBAL` | `NameError` |
| `LOAD_ATTR` | `AttributeError`hoc li mô t tùy ý |
|`BINARY_OP` | `TypeError`, `ZeroDivisionError`, ngoi l ca người dùng |
|`CALL`| Li đối s hoc ngoi l callee |
|`IMPORT_NAME` | `ImportError`, li thc thi mô-đun tùy ý |
|`FOR_ITER`| Ngoi l ca trình vòng lp khác vi s cn kit thông thường |
|`STORE_ATTR` | `AttributeError`, li mô t |
|`BUILD_LIST`| Li phân b b nh |

Vòng đánh giá phi cho rng hu hết các hướng dn đều có th tht bi.

## 34.40 An toàn ngoại lệ trong vòng đánh giá

Mi vic thc hin lnh đều cn mt đường dn li.

Đơn gin hóa:```c id="b2kgao"
PyObject *result = operation();
if (result == NULL) {
    goto error;
}
push(result);
```Đường dn li phi:```text id="j5xxqd"
preserve the active exception
release temporary references
restore stack state
find a handler or unwind
update traceback information
avoid clobbering unrelated exception state
```Đây là mt trong nhng phn khó nht khi trin khai trình thông dch.

## 34.41 Ngoại lệ và tính tham chiếu

Các ngoi l là các đối tượng Python nên chúng được tính theo tham chiếu.

Du vết, khung và các đối tượng ngoi l có th hình thành các chu trình:```text id="olvwqs"
exception
    traceback
        frame
            locals
                exception
```CPython có hành vi dn dp đặc bit xung quanh các biến ngoi l để gim các chu k này. Trình thu gom rác tun hoàn cũng có th thu thp các chu k không th truy cp được.

Tuy nhiên, vic lưu tr ngoi l có th kéo dài tui th ca đối tượng.

## 34.42 Chuẩn hóa ngoại lệ

Trong ni b, CPython thường cn bình thường hóa mt ngoi l để có mt trường hp ngoi l c th.

Các hình thc đầu vào:```python id="dzbie3"
raise ValueError
raise ValueError("bad")
```C hai đều tr thành mt loi ngoi l và mt th hin.

Chun hóa đảm bo mã sau này có th kim tra:```text id="zqj7jd"
exception class
exception instance
traceback
cause
context
notes
```Vic chun hóa ngoi l có th t nó tht bi nếu vic xây dng phiên bn ngoi l không thành công.

## 34.43 Ghi chú ngoại lệ

Các ngoi l ca Python có th mang theo ghi chú.```python id="j1c2ow"
try:
    raise ValueError("bad")
except ValueError as exc:
    exc.add_note("while parsing config")
    raise
```Ghi chú cung cp văn bn chn đoán b sung trong đầu ra truy nguyên.

Chúng được lưu tr trên đối tượng ngoi l và không thay đổi hành vi khp.

## 34.44 Lỗi cú pháp

Li cú pháp cũng là ngoi l, nhưng chúng phát sinh trước khi thc thi mã byte thông thường.```python id="7eglix"
eval("if")
```tăng lên`SyntaxError`.

Các ngoi l trong giai đon biên dch bao gm:```text id="11480v"
SyntaxError
IndentationError
TabError
```Nhng điu này xy ra trong quá trình phân tích cú pháp hoc biên dch, trước khi vòng đánh giá thc thi mã kết qu.

## 34,45 Lỗi bộ nhớ

Li phân b tăng lên`MemoryError`khi CPython có th báo cáo nó.

Các hot động ví d có th phân b:```text id="u0gk53"
creating objects
building lists
creating strings
expanding dictionaries
constructing tracebacks
formatting exception messages
```Bn thân vic x lý ngoi l có th phân b, do đó, thi gian chy phi cn thn khi báo cáo tình trng b nh thp.

## 34.46 Tín hiệu và ngắt bàn phím`KeyboardInterrupt`thường được nâng lên khi trình thông dịch xử lý tín hiệu ngắt như Ctrl-C.

Tín hiu không được x lý theo hướng dn máy tùy ý. CPython ghi li trng thái tín hiu đang ch x lý và kim tra ti các đim an toàn trong vòng đánh giá.

Khi được x lý, trình thông dch s đưa ra`KeyboardInterrupt`trong lung thc thi.

Đây là mt ví d khác v máy móc ngoi l phc v lung điu khin bên ngoài.

## 34.47 Thoát hệ thống`sys.exit()`tăng lên`SystemExit`.

```python id="qyxowo"
import sys
sys.exit(1)
```Nếu không b bt, trình thông dch s thoát vi trng thái đã cho.

Bi vì nó là mt ngoi l nên nó có th b bt:```python id="yl2p70"
try:
    sys.exit(1)
except SystemExit:
    print("caught")
```Đây là lý do ti sao`SystemExit`bt ngun trc tiếp t`BaseException`, rt rng`except Exception`trình x lý thường không ngăn chn quá trình thoát.

## 34.48 Những hiểu lầm phổ biến

| Hiu lm | Đúng mu |
|---|---|
| Ngoi l ch dành cho li | H cũng trin khai các giao thc lp, thoát, hy và điu khin |
| Truy nguyên ch là văn bn | Đó là mt chui các bn ghi khung |
|`except Exception`nm bt mi th | Nó không bt được tt c`BaseException`lp con |
|`finally`luôn gi nguyên li ban đầu | Li nhun hoc tăng trong`finally`có th thay thế nó |
|`with`ch các cuc gi`close`| Nó gi`__enter__`Và`__exit__`, vi các chi tiết ngoi l |
|`hasattr`không có tác dng ph | Nó thc hin tra cu thuc tính và có th chy mã người dùng |
| Mã C tr v trc tiếp các đối tượng ngoi l | Thông thường nó đặt trng thái ngoi l và tr v li canh gác |
| Lưu tr ngoi l là vô hi | Nó có th gi li du vết, khung và cc b ln |

## 34,49 Chiến lược đọc

Để nghiên cu cách x lý ngoi l, hãy phân tích các ví d nh.

Bt đầu vi:```python id="d0qfxt"
def f(x):
    try:
        return 10 / x
    except ZeroDivisionError:
        return 0
```Sau đó kim tra:```python id="lefgod"
import dis
dis.dis(f)
```Đồng thi kim tra đầu ra ca bng ngoi l khi có sn:```python id="mj1mrk"
dis.show_code(f)
```Sau đó kim tra:```python id="fo0fk2"
try/finally
try/except/else
with statements
raise from
bare raise
generators with return
ExceptionGroup and except*
```Đối vi mi trường hp, theo dõi:```text id="pag3xt"
where the protected range begins
where the handler begins
what stack cleanup is required
which exception is active
whether the frame returns or unwinds
what traceback is retained
```## 34.50 Tóm tắt chương

X lý ngoi l trong CPython là mt h thng lung điu khin có cu trúc. Nó s dng các đối tượng ngoi l, lưu tr ngoi l trng thái lung, gii phóng khung, xây dng truy nguyên, bng ngoi l, khôi phc ngăn xếp, khp trình x lý và các khi dn dp.

Mô hình ct lõi là:```text id="huu536"
operation fails
    
exception state is set
    
current frame looks for a handler
    
handler found: restore stack and jump
    
no handler: unwind frame and propagate
    
top level: print traceback or terminate
```Các ngoi l kết ni nhiu phn ca thi gian chy: thc thi mã byte, lnh gi hàm, trình qun lý ng cnh, trình to, coroutine, nhp, tra cu thuc tính, quy ước li API C, x lý tín hiu và qun lý b nh.

Hiu các ngoi l có nghĩa là hiu c cách x lý li và phn chính ca cơ chế điu khin lung ca Python.