3.8 KiB
3.8 KiB
09 - 异常处理
本章待修订(机制与实现存在偏差,见各节标注)
说明:本章讲的是语言层
try/except(错误码 + 错误消息出参)。运行期崩溃 / 按键时打印的调用栈回溯是另一套机制,见 17-traceback.md。
Viper 支持 Python 风格的 try/except/finally 异常处理,采用基于错误码 + 错误消息出参的传播机制(不使用 C++ 风格的零开销异常)。
异常处理机制
编译器自动为可能抛出异常的函数追加 __eh_code_out__(i32*) 与 __eh_msg_out__(i8**) 出参;调用点传入接收缓冲,调用后检查 msg != NULL,按 code 匹配 except。
try / except
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 |
自定义异常
class DiskFullError(Exception):
pass
class ReadOnlyError(DiskFullError):
pass
自定义异常会自动分配递增的错误码(从 100 开始),并支持继承匹配。
多异常捕获
语法暂不支持(期望)。
try:
result = operation()
except (ValueError, TypeError):
serial.puts("Value or Type error\n")
获取异常信息
try:
result = operation()
except Exception as e:
serial.puts("Error occurred\n")
try / finally
普通函数中尚未实现(仅协程子集支持纯 try/finally)——期望/后续修正
try:
result = operation()
finally:
cleanup()
finally 块无论是否发生异常都会执行。
try / except / finally
普通函数中尚未实现(仅协程子集支持纯 try/finally)——期望/后续修正
try:
result = operation()
except ValueError:
handle_value_error()
finally:
cleanup()
raise 语句
抛出异常
raise ValueError("invalid value")
抛出自定义异常
raise MyCustomError("something went wrong")
重新抛出异常
当前裸 raise 不重新抛出(返回默认值),期望实现重抛当前异常。
raise
StopIteration
StopIteration 有特殊处理,用于迭代器协议:
raise StopIteration
异常处理的编译实现
函数签名变换
可能抛出异常的函数会自动添加错误输出参数:
def risky_operation() -> t.CInt:
if error:
raise ValueError("bad value")
return 0
编译后等价于:
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;
}
调用点变换
try:
result = risky_operation()
except ValueError:
handle_error()
编译后等价于:
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();
}
}
异常继承匹配
异常匹配支持继承体系。捕获父类异常时,子类异常也会被匹配:
class FileSystemError(Exception):
pass
class FileNotFoundError(FileSystemError):
pass
class PermissionError(FileSystemError):
pass
try:
operation()
except FileSystemError:
# 也会捕获 FileNotFoundError 和 PermissionError
handle_fs_error()