一、语法错误 vs 编译错误
Python 语法错误
while True print('Hello world')
# SyntaxError: invalid syntax
Rust 编译错误
fn main() {
while true println!("Hello world");
// 错误:期望 `{`,找到 `println`
}
关键差异:
Python:运行时解析错误
Rust:编译时检查,更早发现错误
二、异常 vs Result 类型
Python 异常处理
# 自动抛出异常
10 * (1/0) # ZeroDivisionError
4 + spam*3 # NameError
'2' + 2 # TypeError
Rust 错误处理
// 显式处理可能失败的操作
let result: Result<i32, &str> = Ok(42);
let error: Result<i32, &str> = Err("Something went wrong");
// 必须处理 Result 类型
match result {
Ok(value) => println!("Value: {}", value),
Err(e) => println!("Error: {}", e),
}
三、异常处理机制对比
Python try-except
while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("Oops! That was no valid number. Try again...")
except (RuntimeError, TypeError, NameError) as e:
print(f"Other error: {e}")
else:
print("No exception occurred")
finally:
print("This always runs")
Rust Result 处理
use std::io;
fn get_number() -> Result<i32, io::Error> {
let mut input = String::new();
loop {
println!("Please enter a number: ");
io::stdin().read_line(&mut input)?;
match input.trim().parse() {
Ok(num) => return Ok(num),
Err(_) => {
println!("Oops! That was no valid number. Try again...");
input.clear();
continue;
}
}
}
}
// 使用 ? 操作符传播错误
fn process() -> Result<(), io::Error> {
let x = get_number()?; // 自动传播错误
println!("You entered: {}", x);
Ok(())
}
四、抛出/引发异常对比
Python raise
def validate_age(age):
if age < 0:
raise ValueError("Age cannot be negative")
return age
try:
validate_age(-1)
except ValueError as e:
print(f"Caught exception: {e}")
Rust Result 返回
fn validate_age(age: i32) -> Result<i32, &'static str> {
if age < 0 {
return Err("Age cannot be negative");
}
Ok(age)
}
match validate_age(-1) {
Ok(age) => println!("Valid age: {}", age),
Err(e) => println!("Error: {}", e),
}
五、异常链 vs 错误转换
Python 异常链
try:
open("database.sqlite")
except OSError as e:
raise RuntimeError("Unable to handle error") from e
Rust 错误转换
use std::fs::File;
use std::io;
fn open_database() -> Result<File, io::Error> {
File::open("database.sqlite")
.map_err(|e| io::Error::new(io::ErrorKind::Other, "Unable to handle error"))
}
六、自定义异常/错误
Python 自定义异常
class MyError(Exception):
def __init__(self, message, code):
super().__init__(message)
self.code = code
try:
raise MyError("Something went wrong", 500)
except MyError as e:
print(f"Error {e.code}: {e}")
Rust 自定义错误
use thiserror::Error;
#[derive(Error, Debug)]
enum MyError {
#[error("Something went wrong with code {0}")]
WithCode(i32),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
fn might_fail() -> Result<(), MyError> {
if condition {
Err(MyError::WithCode(500))
} else {
Ok(())
}
}
七、清理操作对比
Python finally
try:
f = open("file.txt")
# 处理文件
finally:
f.close() # 总是执行
Rust Drop trait
struct FileWrapper {
file: File,
}
impl Drop for FileWrapper {
fn drop(&mut self) {
// 自动清理,类似 finally
// 文件会在离开作用域时自动关闭
}
}
{
let file_wrapper = FileWrapper { file: File::open("file.txt")? };
// 使用文件
} // 这里自动调用 drop()
八、资源管理对比
Python with 语句
with open("myfile.txt") as f:
for line in f:
print(line, end="")
# 文件自动关闭
Rust RAII 模式
use std::fs::File;
use std::io::{BufRead, BufReader};
{
let file = File::open("myfile.txt")?;
let reader = BufReader::new(file);
for line in reader.lines() {
println!("{}", line?);
}
} // 文件自动关闭
九、批量错误处理对比
Python ExceptionGroup
excs = []
for test in tests:
try:
test.run()
except Exception as e:
excs.append(e)
if excs:
raise ExceptionGroup("Test Failures", excs)
Rust 错误收集
use anyhow::Result;
let mut errors = Vec::new();
for test in tests {
if let Err(e) = test.run() {
errors.push(e);
}
}
if !errors.is_empty() {
// 处理多个错误
}
十、错误注释/上下文
Python add_note()
try:
raise TypeError('bad type')
except Exception as e:
e.add_note('Additional context')
raise
Rust 错误上下文
use anyhow::{Context, Result};
fn process_file() -> Result<()> {
let content = std::fs::read_to_string("file.txt")
.context("Failed to read file")?;
Ok(())
}
十一、🔑 核心哲学差异
特性 | Python | Rust |
---|---|---|
错误处理 | 异常机制 | Result/Option 类型 |
错误发现 | 运行时 | 编译时 |
强制处理 | 可选 | 必须处理 Result |
性能 | 异常堆栈跟踪有开销 | 零成本抽象 |
代码流程 | 控制流跳转 | 显式处理每个可能错误 |
资源清理 | finally 或 with | RAII 和 Drop |
十二、💡 最佳实践
Python 异常处理建议
具体异常:捕获具体异常而不是通用的 Exception
异常信息:提供清晰的错误信息
资源清理:使用 with 语句管理资源
异常链:使用 from 保留原始异常信息
Rust 错误处理建议
显式处理:使用 match 或 ? 操作符处理所有错误
错误类型:定义清晰的错误类型
错误转换:使用 map_err 或 库如 anyhow/thiserror
尽早返回:使用 ? 操作符传播错误
十三、🎯 转换思维
从 Python 到 Rust
忘记 try-except,学习 match 和 Result
资源管理从 with 转到 RAII
错误信息从异常消息转到枚举变体
从 Rust 到 Python
享受异常处理的简洁性
但要注意捕获过于宽泛的异常
利用 with 语句简化资源管理
两种语言都有优秀的错误处理机制,Python 更注重开发效率,Rust 更注重安全性和性能!