异常处理
try-except 语句
Python 异常处理
基本异常处理
python
# Python - 基本异常处理
def divide_numbers(a, b):
try:
result = a / b
return result
except ZeroDivisionError:
print("错误:除数不能为零")
return None
except TypeError:
print("错误:参数类型不正确")
return None
# 测试异常处理
print(divide_numbers(10, 2)) # 5.0
print(divide_numbers(10, 0)) # 错误:除数不能为零
print(divide_numbers("10", 2)) # 错误:参数类型不正确
# 多个异常类型
def process_data(data):
try:
if isinstance(data, str):
return int(data)
elif isinstance(data, (int, float)):
return data
else:
raise ValueError("不支持的数据类型")
except (ValueError, TypeError) as e:
print(f"数据处理错误: {e}")
return None
# 测试多种异常
print(process_data("123")) # 123
print(process_data(456)) # 456
print(process_data("abc")) # 数据处理错误: invalid literal for int() with base 10: 'abc'
print(process_data([1, 2, 3])) # 数据处理错误: 不支持的数据类型完整的异常处理结构
python
# Python - 完整的异常处理结构
def file_operations(filename):
try:
# 尝试打开文件
with open(filename, 'r', encoding='utf-8') as f:
content = f.read()
print("文件读取成功")
return content
except FileNotFoundError:
print(f"文件 {filename} 不存在")
return None
except PermissionError:
print(f"没有权限读取文件 {filename}")
return None
except UnicodeDecodeError:
print(f"文件 {filename} 编码错误")
return None
except Exception as e:
print(f"未知错误: {e}")
return None
else:
# 只有在没有异常时执行
print("文件操作完成")
finally:
# 无论是否有异常都会执行
print("清理资源")
# 测试文件操作
file_operations("nonexistent.txt")
file_operations("example.txt")异常链和重新抛出
python
# Python - 异常链和重新抛出
def low_level_function():
try:
result = 10 / 0
except ZeroDivisionError as e:
raise RuntimeError("低级函数出错") from e
def high_level_function():
try:
low_level_function()
except RuntimeError as e:
print(f"高级函数捕获到错误: {e}")
print(f"原始错误: {e.__cause__}")
# 测试异常链
high_level_function()
# 重新抛出异常
def process_user_input(user_input):
try:
age = int(user_input)
if age < 0 or age > 150:
raise ValueError("年龄必须在 0-150 之间")
return age
except ValueError as e:
print(f"输入验证失败: {e}")
raise # 重新抛出异常
# 测试重新抛出
try:
age = process_user_input("abc")
except ValueError:
print("程序无法处理无效输入")JavaScript 异常处理
基本异常处理
javascript
// JavaScript - 基本异常处理
function divideNumbers(a, b) {
try {
const result = a / b;
if (!isFinite(result)) {
throw new Error("计算结果无效");
}
return result;
} catch (error) {
if (error.message === "计算结果无效") {
console.log("错误:除数不能为零");
} else {
console.log("错误:参数类型不正确");
}
return null;
}
}
// 测试异常处理
console.log(divideNumbers(10, 2)); // 5
console.log(divideNumbers(10, 0)); // 错误:除数不能为零
console.log(divideNumbers("10", 2)); // 错误:参数类型不正确
// 多个异常类型
function processData(data) {
try {
if (typeof data === "string") {
const result = parseInt(data);
if (isNaN(result)) {
throw new Error("无法转换为数字");
}
return result;
} else if (typeof data === "number") {
return data;
} else {
throw new Error("不支持的数据类型");
}
} catch (error) {
console.log(`数据处理错误: ${error.message}`);
return null;
}
}
// 测试多种异常
console.log(processData("123")); // 123
console.log(processData(456)); // 456
console.log(processData("abc")); // 数据处理错误: 无法转换为数字
console.log(processData([1, 2, 3])); // 数据处理错误: 不支持的数据类型完整的异常处理结构
javascript
// JavaScript - 完整的异常处理结构
async function fileOperations(filename) {
let fileHandle = null;
try {
// 尝试打开文件
fileHandle = await fs.open(filename, "r");
const content = await fileHandle.readFile("utf-8");
console.log("文件读取成功");
return content;
} catch (error) {
if (error.code === "ENOENT") {
console.log(`文件 ${filename} 不存在`);
} else if (error.code === "EACCES") {
console.log(`没有权限读取文件 ${filename}`);
} else {
console.log(`未知错误: ${error.message}`);
}
return null;
} finally {
// 无论是否有异常都会执行
if (fileHandle) {
await fileHandle.close();
}
console.log("清理资源");
}
}
// 测试文件操作
fileOperations("nonexistent.txt");
fileOperations("example.txt");异常链和重新抛出
javascript
// JavaScript - 异常链和重新抛出
function lowLevelFunction() {
try {
const result = 10 / 0;
return result;
} catch (error) {
throw new Error("低级函数出错", { cause: error });
}
}
function highLevelFunction() {
try {
lowLevelFunction();
} catch (error) {
console.log(`高级函数捕获到错误: ${error.message}`);
console.log(`原始错误: ${error.cause}`);
}
}
// 测试异常链
highLevelFunction();
// 重新抛出异常
function processUserInput(userInput) {
try {
const age = parseInt(userInput);
if (isNaN(age) || age < 0 || age > 150) {
throw new Error("年龄必须在 0-150 之间");
}
return age;
} catch (error) {
console.log(`输入验证失败: ${error.message}`);
throw error; // 重新抛出异常
}
}
// 测试重新抛出
try {
const age = processUserInput("abc");
} catch (error) {
console.log("程序无法处理无效输入");
}自定义异常
Python 自定义异常
python
# Python - 自定义异常类
class ValidationError(Exception):
"""验证错误异常"""
def __init__(self, message, field=None):
self.message = message
self.field = field
super().__init__(self.message)
class DatabaseError(Exception):
"""数据库错误异常"""
def __init__(self, message, error_code=None):
self.message = message
self.error_code = error_code
super().__init__(self.message)
# 使用自定义异常
def validate_user_data(data):
"""验证用户数据"""
if not isinstance(data, dict):
raise ValidationError("数据必须是字典类型")
if 'name' not in data:
raise ValidationError("缺少姓名字段", field='name')
if 'age' not in data:
raise ValidationError("缺少年龄字段", field='age')
if not isinstance(data['age'], int) or data['age'] < 0:
raise ValidationError("年龄必须是正整数", field='age')
return True
# 测试自定义异常
try:
validate_user_data({"name": "Alice"})
except ValidationError as e:
print(f"验证错误: {e.message}, 字段: {e.field}")
try:
validate_user_data({"name": "Bob", "age": -5})
except ValidationError as e:
print(f"验证错误: {e.message}, 字段: {e.field}")JavaScript 自定义异常
javascript
// JavaScript - 自定义异常类
class ValidationError extends Error {
constructor(message, field = null) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
class DatabaseError extends Error {
constructor(message, errorCode = null) {
super(message);
this.name = "DatabaseError";
this.errorCode = errorCode;
}
}
// 使用自定义异常
function validateUserData(data) {
if (typeof data !== "object" || data === null) {
throw new ValidationError("数据必须是对象类型");
}
if (!data.hasOwnProperty("name")) {
throw new ValidationError("缺少姓名字段", "name");
}
if (!data.hasOwnProperty("age")) {
throw new ValidationError("缺少年龄字段", "age");
}
if (typeof data.age !== "number" || data.age < 0) {
throw new ValidationError("年龄必须是正整数", "age");
}
return true;
}
// 测试自定义异常
try {
validateUserData({ name: "Alice" });
} catch (error) {
if (error instanceof ValidationError) {
console.log(`验证错误: ${error.message}, 字段: ${error.field}`);
}
}
try {
validateUserData({ name: "Bob", age: -5 });
} catch (error) {
if (error instanceof ValidationError) {
console.log(`验证错误: ${error.message}, 字段: ${error.field}`);
}
}异常处理最佳实践
Python 最佳实践
python
# Python - 异常处理最佳实践
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class DataProcessor:
def __init__(self):
self.processed_count = 0
self.error_count = 0
def process_item(self, item):
"""处理单个数据项"""
try:
# 验证数据
if not self._validate_item(item):
raise ValueError("数据验证失败")
# 处理数据
result = self._transform_item(item)
# 记录成功
self.processed_count += 1
logger.info(f"成功处理项目: {item}")
return result
except ValueError as e:
# 处理已知错误
self.error_count += 1
logger.warning(f"数据验证错误: {e}")
return None
except Exception as e:
# 处理未知错误
self.error_count += 1
logger.error(f"处理项目时发生未知错误: {e}", exc_info=True)
return None
def _validate_item(self, item):
"""验证数据项"""
return isinstance(item, (int, float, str)) and item is not None
def _transform_item(self, item):
"""转换数据项"""
if isinstance(item, str):
return item.upper()
elif isinstance(item, (int, float)):
return item * 2
else:
raise ValueError("不支持的数据类型")
def get_statistics(self):
"""获取处理统计"""
return {
'processed': self.processed_count,
'errors': self.error_count,
'success_rate': self.processed_count / (self.processed_count + self.error_count) if (self.processed_count + self.error_count) > 0 else 0
}
# 使用最佳实践
processor = DataProcessor()
items = [1, "hello", None, 3.14, "world"]
for item in items:
result = processor.process_item(item)
stats = processor.get_statistics()
print(f"处理统计: {stats}")JavaScript 最佳实践
javascript
// JavaScript - 异常处理最佳实践
class DataProcessor {
constructor() {
this.processedCount = 0;
this.errorCount = 0;
}
processItem(item) {
try {
// 验证数据
if (!this._validateItem(item)) {
throw new Error("数据验证失败");
}
// 处理数据
const result = this._transformItem(item);
// 记录成功
this.processedCount++;
console.log(`成功处理项目: ${item}`);
return result;
} catch (error) {
// 处理错误
this.errorCount++;
if (error.message === "数据验证失败") {
console.warn(`数据验证错误: ${error.message}`);
} else {
console.error(`处理项目时发生未知错误: ${error.message}`);
console.error(error.stack);
}
return null;
}
}
_validateItem(item) {
return (
item !== null &&
item !== undefined &&
(typeof item === "string" || typeof item === "number")
);
}
_transformItem(item) {
if (typeof item === "string") {
return item.toUpperCase();
} else if (typeof item === "number") {
return item * 2;
} else {
throw new Error("不支持的数据类型");
}
}
getStatistics() {
const total = this.processedCount + this.errorCount;
return {
processed: this.processedCount,
errors: this.errorCount,
successRate: total > 0 ? this.processedCount / total : 0,
};
}
}
// 使用最佳实践
const processor = new DataProcessor();
const items = [1, "hello", null, 3.14, "world"];
items.forEach((item) => {
processor.processItem(item);
});
const stats = processor.getStatistics();
console.log(`处理统计:`, stats);异常处理对比
| 特性 | Python | JavaScript |
|---|---|---|
| 基本语法 | try/except | try/catch |
| 异常类型 | Exception 类 | Error 类 |
| 多个异常 | except (Type1, Type2): | 多个 catch 块 |
| 异常信息 | except Exception as e: | catch (error) {} |
| 清理代码 | finally | finally |
| 重新抛出 | raise | throw |
| 异常链 | raise NewError() from e | throw new Error("msg", {cause: e}) |
练习
- 创建一个文件读取函数,处理各种可能的异常
参考答案:
python
# Python
def read_file(filename):
try:
with open(filename, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
print('文件未找到')
except PermissionError:
print('没有权限')
except Exception as e:
print('其他错误:', e)javascript
// JavaScript (Node.js)
const fs = require("fs");
function readFile(filename) {
try {
return fs.readFileSync(filename, "utf-8");
} catch (err) {
if (err.code === "ENOENT") {
console.log("文件未找到");
} else if (err.code === "EACCES") {
console.log("没有权限");
} else {
console.log("其他错误:", err);
}
}
}- 实现一个数据验证类,使用自定义异常
参考答案:
python
# Python
class ValidationError(Exception):
pass
class Validator:
def validate_age(self, age):
if not (0 <= age <= 120):
raise ValidationError("年龄不合法")
try:
Validator().validate_age(150)
except ValidationError as e:
print(e)javascript
// JavaScript
class ValidationError extends Error {}
class Validator {
validateAge(age) {
if (age < 0 || age > 120) {
throw new ValidationError("年龄不合法");
}
}
}
try {
new Validator().validateAge(150);
} catch (e) {
console.log(e.message);
}- 创建一个网络请求函数,处理连接超时和错误
参考答案:
python
# Python
import requests
try:
response = requests.get("https://httpbin.org/delay/3", timeout=1)
except requests.Timeout:
print("请求超时")
except requests.RequestException as e:
print("请求错误:", e)javascript
// JavaScript (Node.js)
const axios = require("axios");
axios
.get("https://httpbin.org/delay/3", { timeout: 1000 })
.then((res) => console.log(res.status))
.catch((err) => {
if (err.code === "ECONNABORTED") {
console.log("请求超时");
} else {
console.log("请求错误:", err.message);
}
});- 实现一个计算器类,处理除零和类型错误
参考答案:
python
# Python
class Calculator:
def divide(self, a, b):
try:
return a / b
except ZeroDivisionError:
print("除数不能为零")
except TypeError:
print("类型错误")
calc = Calculator()
calc.divide(10, 0)
calc.divide(10, "a")javascript
// JavaScript
class Calculator {
divide(a, b) {
try {
if (typeof a !== "number" || typeof b !== "number") {
throw new TypeError("类型错误");
}
if (b === 0) {
throw new Error("除数不能为零");
}
return a / b;
} catch (e) {
console.log(e.message);
}
}
}
const calc = new Calculator();
calc.divide(10, 0);
calc.divide(10, "a");- 比较 Python 和 JavaScript 的异常处理机制差异
参考答案:
- Python 使用 try/except/finally,支持自定义异常类,异常类型丰富。
- JavaScript 使用 try/catch/finally,异常为 Error 派生类,类型较少。
- Python 支持多 except 分支,JS 只能用 if 判断 error 类型。
下一步
现在你已经了解了异常处理,接下来我们将学习项目依赖管理。