# 09 - 异常处理 Viper 支持 Python 风格的 `try/except/finally` 异常处理,编译为基于 jmp_buf 和错误码的 C 级别异常处理机制。 ## 异常处理机制 Viper 的异常处理不使用 C++ 风格的零开销异常,而是通过函数参数传递错误码和错误消息实现。编译器自动为可能抛出异常的函数添加 `__eh_msg_out__` 和 `__eh_code_out__` 参数。 ## try / except ```python try: result = risky_operation() except ValueError: serial.puts("ValueError occurred\n") except OSError: serial.puts("OSError occurred\n") except Exception: serial.puts("Unknown error\n") ``` ### 内置异常类型 Viper 预定义了以下异常类型及其错误码: | 异常类型 | 错误码 | |---------|--------| | `ValueError` | 1 | | `TypeError` | 2 | | `RuntimeError` | 3 | | `ZeroDivisionError` | 4 | | `IndexError` | 5 | | `KeyError` | 6 | | `IOError` | 7 | | `OSError` | 8 | | `AssertionError` | 9 | | `Exception` | 99 | ### 自定义异常 ```python class DiskFullError(Exception): pass class ReadOnlyError(DiskFullError): pass ``` 自定义异常会自动分配递增的错误码(从 100 开始),并支持继承匹配。 ### 多异常捕获 ```python try: result = operation() except (ValueError, TypeError): serial.puts("Value or Type error\n") ``` ### 获取异常信息 ```python try: result = operation() except Exception as e: serial.puts("Error occurred\n") ``` ## try / finally ```python try: result = operation() finally: cleanup() ``` `finally` 块无论是否发生异常都会执行。 ## try / except / finally ```python try: result = operation() except ValueError: handle_value_error() finally: cleanup() ``` ## raise 语句 ### 抛出异常 ```python raise ValueError("invalid value") ``` ### 抛出自定义异常 ```python raise MyCustomError("something went wrong") ``` ### 重新抛出异常 ```python raise ``` ### StopIteration `StopIteration` 有特殊处理,用于迭代器协议: ```python raise StopIteration ``` ## 异常处理的编译实现 ### 函数签名变换 可能抛出异常的函数会自动添加错误输出参数: ```python def risky_operation() -> t.CInt: if error: raise ValueError("bad value") return 0 ``` 编译后等价于: ```c int risky_operation(char** __eh_msg_out__, int* __eh_code_out__) { if (error) { *__eh_code_out__ = 1; // ValueError code *__eh_msg_out__ = "bad value"; return 0; } return 0; } ``` ### 调用点变换 ```python try: result = risky_operation() except ValueError: handle_error() ``` 编译后等价于: ```c char* __eh_msg = NULL; int __eh_code = 0; int result = risky_operation(&__eh_msg, &__eh_code); if (__eh_msg != NULL) { if (__eh_code == 1) { // ValueError handle_error(); } } ``` ## 异常继承匹配 异常匹配支持继承体系。捕获父类异常时,子类异常也会被匹配: ```python class FileSystemError(Exception): pass class FileNotFoundError(FileSystemError): pass class PermissionError(FileSystemError): pass try: operation() except FileSystemError: # 也会捕获 FileNotFoundError 和 PermissionError handle_fs_error() ```