Python:异常处理
This commit is contained in:
parent
3cf8f867b5
commit
07cec1aed2
3
.obsidian/app.json
vendored
3
.obsidian/app.json
vendored
@ -18,5 +18,6 @@
|
|||||||
"showFrontmatter": true,
|
"showFrontmatter": true,
|
||||||
"vimMode": false,
|
"vimMode": false,
|
||||||
"newLinkFormat": "absolute",
|
"newLinkFormat": "absolute",
|
||||||
"propertiesInDocument": "visible"
|
"propertiesInDocument": "visible",
|
||||||
|
"useMarkdownLinks": true
|
||||||
}
|
}
|
@ -344,128 +344,3 @@ class Dog(AbstractAnimal, AnimalBehaviour):
|
|||||||
return "The dog is sleeping."
|
return "The dog is sleeping."
|
||||||
```
|
```
|
||||||
|
|
||||||
## 异常处理
|
|
||||||
|
|
||||||
### 异常的概念
|
|
||||||
|
|
||||||
在 Python 中,异常是程序运行期间发生的错误事件,它会中断常规程序的执行流程。当程序执行过程中遇到错误时,Python 解释器会自动引发(raise)一个异常。
|
|
||||||
|
|
||||||
异常是一种特殊的对象,它包含了有关错误的详细信息,例如错误类型和错误发生时的程序状态。Python 内置了很多标准异常类型,如 `ValueError`,`TypeError`,`IndexError` 等,每种类型都对应了一类特定的错误。
|
|
||||||
|
|
||||||
我们可以使用异常处理机制来捕获(catch)异常。通过处理异常,我们可以决定在出现错误时程序如何响应,而不是让程序直接崩溃。这对于构建健壮和稳定的程序至关重要。
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
graph TB
|
|
||||||
BaseException --> SystemExit
|
|
||||||
BaseException --> KeyboardInterrupt
|
|
||||||
BaseException --> GeneratorExit
|
|
||||||
BaseException --> Exception
|
|
||||||
Exception --> StopIteration
|
|
||||||
Exception --> ArithmeticError
|
|
||||||
ArithmeticError --> FloatingPointError
|
|
||||||
ArithmeticError --> OverflowError
|
|
||||||
ArithmeticError --> ZeroDivisionError
|
|
||||||
Exception --> AssertionError
|
|
||||||
Exception --> AttributeError
|
|
||||||
Exception --> EOFError
|
|
||||||
Exception --> ImportError
|
|
||||||
Exception --> ModuleNotFoundError
|
|
||||||
Exception --> LookupError
|
|
||||||
LookupError --> IndexError
|
|
||||||
LookupError --> KeyError
|
|
||||||
Exception --> NameError
|
|
||||||
NameError --> UnboundLocalError
|
|
||||||
Exception --> OSError
|
|
||||||
OSError --> IOError
|
|
||||||
Exception --> RuntimeError
|
|
||||||
RuntimeError --> NotImplementedError
|
|
||||||
RuntimeError --> RecursionError
|
|
||||||
Exception --> SyntaxError
|
|
||||||
Exception --> SystemError
|
|
||||||
Exception --> TypeError
|
|
||||||
Exception --> ValueError
|
|
||||||
Exception --> UnicodeError
|
|
||||||
```
|
|
||||||
|
|
||||||
### 异常处理关键字
|
|
||||||
|
|
||||||
Python 中处理异常的关键字主要有四个:`try`,`except`,`finally`,`else`。
|
|
||||||
|
|
||||||
- `try`: 你可以把可能会引发异常的代码放在 `try` 块中。
|
|
||||||
- `except`: 当 `try` 块中的代码引发异常时,`except` 块中的代码将被执行。你可以在 `except` 后面指定你想捕获的异常类型。一个 `try` 块后面可以跟随多个 `except` 块,用于捕获不同类型的异常。
|
|
||||||
- `finally`: 无论 `try` 块中的代码是否引发异常,`finally` 块中的代码都将被执行。这常用于执行一些无论异常是否发生都需要执行的清理操作,如关闭文件。
|
|
||||||
- `else`: 如果 `try` 块中的代码没有引发异常,那么 `else` 块中的代码将被执行。`else` 关键字是可选的。
|
|
||||||
|
|
||||||
```Python
|
|
||||||
try:
|
|
||||||
# 这里是可能抛出异常的代码
|
|
||||||
result = 10 / 0
|
|
||||||
except ZeroDivisionError:
|
|
||||||
# 这里是处理ZeroDivisionError异常的代码
|
|
||||||
print("Cannot divide by zero!")
|
|
||||||
else:
|
|
||||||
# 这里是try代码块成功执行后的代码
|
|
||||||
print("Operation successful.")
|
|
||||||
finally:
|
|
||||||
# 这里是无论是否发生异常都会执行的代码
|
|
||||||
print("This is the finally block.")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Python 内置标准异常
|
|
||||||
|
|
||||||
| 异常名 | 描述 |
|
|
||||||
| --------------------- | ----------------------------------- |
|
|
||||||
| `BaseException` | 所有异常的基类 |
|
|
||||||
| `SystemExit` | 解释器请求退出 |
|
|
||||||
| `KeyboardInterrupt` | 用户中断执行 (通常是输入^C) |
|
|
||||||
| `Exception` | 常规错误的基类 |
|
|
||||||
| `StopIteration` | 迭代器没有更多的值 |
|
|
||||||
| `GeneratorExit` | 生成器 (generator) 发生异常来通知退出 |
|
|
||||||
| `SystemError` | 解释器发现内部错误 |
|
|
||||||
| `SyntaxError` | Python 语法错误 |
|
|
||||||
| `IndentationError` | 缩进错误 |
|
|
||||||
| `TabError` | Tab 和空格混用 |
|
|
||||||
| `NameError` | 未声明/初始化对象 (没有属性) |
|
|
||||||
| `UnboundLocalError` | 访问未初始化的本地变量 |
|
|
||||||
| `AttributeError` | 对象没有这个属性 |
|
|
||||||
| `TypeError` | 对类型无效的操作 |
|
|
||||||
| `AssertionError` | 断言语句失败 |
|
|
||||||
| `ImportError` | 导入模块/对象失败 |
|
|
||||||
| `ModuleNotFoundError` | 找不到模块 |
|
|
||||||
| `LookupError` | 无效数据查询的基类 |
|
|
||||||
| `IndexError` | 序列中没有此索引 (index) |
|
|
||||||
| `KeyError` | 映射中没有这个键 |
|
|
||||||
| `ValueError` | 传入无效的参数 |
|
|
||||||
| `UnicodeError` | Unicode 相关的错误 |
|
|
||||||
| `ArithmeticError` | 数学运算基类 |
|
|
||||||
| `FloatingPointError` | 浮点计算错误 |
|
|
||||||
| `OverflowError` | 数值运算超出最大限制 |
|
|
||||||
| `ZeroDivisionError` | 除 (或取模) 零 (所有数据类型) |
|
|
||||||
| `EnvironmentError` | 操作系统错误的基类 |
|
|
||||||
| `IOError` | 输入/输出操作失败 |
|
|
||||||
| `OSError` | 操作系统错误 |
|
|
||||||
| `EOFError` | 没有内建输入,到达 EOF 标记 |
|
|
||||||
| `RuntimeError` | 一般的运行时错误 |
|
|
||||||
| `NotImplementedError` | 尚未实现的方法 |
|
|
||||||
| `RecursionError` | 超过最大递归深度 |
|
|
||||||
|
|
||||||
### 自定义异常的创建和抛出
|
|
||||||
|
|
||||||
Python 允许你创建自定义的异常类型。为了创建自定义的异常类型,你需要定义一个类,它继承自 `Exception` 类或者它的子类。在你的类中,你可以定义任何你需要的方法,但是通常,自定义的异常类型会非常简单,只提供一些基本的信息。
|
|
||||||
|
|
||||||
要抛出你自定义的异常,你可以使用 `raise` 关键字。在 `raise` 语句后面,你可以指定要抛出的异常类型,以及一个可选的错误消息。
|
|
||||||
|
|
||||||
```Python
|
|
||||||
class CustomError(Exception):
|
|
||||||
"""自定义的异常类型"""
|
|
||||||
|
|
||||||
def __init__(self, message):
|
|
||||||
self.message = message
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 抛出自定义的异常
|
|
||||||
raise CustomError("This is a custom error.")
|
|
||||||
except CustomError as e:
|
|
||||||
# 捕获并处理自定义的异常
|
|
||||||
print("Caught an exception:", e.message)
|
|
||||||
```
|
|
||||||
|
@ -272,7 +272,7 @@ Requests 的异常类型主要分为以下几类:
|
|||||||
- **数据解析错误**:JSONDecodeError 和 DecodeError 表示响应数据解析错误。
|
- **数据解析错误**:JSONDecodeError 和 DecodeError 表示响应数据解析错误。
|
||||||
- **其他**:ConnectionError、InvalidURL 等其他异常。
|
- **其他**:ConnectionError、InvalidURL 等其他异常。
|
||||||
|
|
||||||
可以通过 try except 语句捕获这些异常:
|
可以通过 try except 语句捕获这些 [异常](Tech/programming-language/Python/进阶/异常处理.md):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import requests
|
import requests
|
||||||
|
190
Tech/programming-language/Python/进阶/异常处理.md
Normal file
190
Tech/programming-language/Python/进阶/异常处理.md
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
## 异常的概念
|
||||||
|
|
||||||
|
**在 Python 中,异常是程序运行时发生的错误,它中断了正常的程序流程。**Python 使用异常对象来表示错误。当程序中发生错误时,Python 会创建一个相应的异常对象。若未处理,程序将终止并显示错误信息。
|
||||||
|
|
||||||
|
异常处理是一种编程结构,用于捕获和响应程序中的异常。正确处理异常可以提高程序的健壮性和可靠性,预防中断或崩溃。
|
||||||
|
|
||||||
|
异常是一种特殊对象,包含错误的详细信息,如类型和发生时的状态。Python 内置了许多标准异常类型,例如 `ValueError`、`TypeError`、`IndexError`,每种类型对应特定错误。
|
||||||
|
|
||||||
|
我们**可以通过异常处理机制捕获异常。**处理异常允许我们决定出错时的响应方式,而非直接让程序崩溃。这对构建健壮和稳定的程序至关重要。
|
||||||
|
|
||||||
|
### 异常层次结构
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
BaseException --> SystemExit
|
||||||
|
BaseException --> KeyboardInterrupt
|
||||||
|
BaseException --> GeneratorExit
|
||||||
|
BaseException --> Exception
|
||||||
|
Exception --> StopIteration
|
||||||
|
Exception --> ArithmeticError
|
||||||
|
ArithmeticError --> FloatingPointError
|
||||||
|
ArithmeticError --> OverflowError
|
||||||
|
ArithmeticError --> ZeroDivisionError
|
||||||
|
Exception --> AssertionError
|
||||||
|
Exception --> AttributeError
|
||||||
|
Exception --> EOFError
|
||||||
|
Exception --> ImportError
|
||||||
|
Exception --> ModuleNotFoundError
|
||||||
|
Exception --> LookupError
|
||||||
|
LookupError --> IndexError
|
||||||
|
LookupError --> KeyError
|
||||||
|
Exception --> NameError
|
||||||
|
NameError --> UnboundLocalError
|
||||||
|
Exception --> OSError
|
||||||
|
OSError --> IOError
|
||||||
|
Exception --> RuntimeError
|
||||||
|
RuntimeError --> NotImplementedError
|
||||||
|
RuntimeError --> RecursionError
|
||||||
|
Exception --> SyntaxError
|
||||||
|
Exception --> SystemError
|
||||||
|
Exception --> TypeError
|
||||||
|
Exception --> ValueError
|
||||||
|
Exception --> UnicodeError
|
||||||
|
```
|
||||||
|
|
||||||
|
**Python 的异常遵循一定的层次结构。**在这个层次结构的顶端是 `BaseException` 类,它是所有异常的基类。接着是其他一些内置异常,如 `SystemExit`、`KeyboardInterrupt` 等,这些通常用于系统退出和用户中断。
|
||||||
|
|
||||||
|
紧随其后的是 `Exception` 类,它是大多数内置可被应用程序捕获的错误的基类。从 `Exception` 类派生出更具体的异常类,如 `StopIteration`、`ArithmeticError`、`LookupError` 等,这些类又有自己的子类,分别对应特定的错误情况。
|
||||||
|
|
||||||
|
## 基本异常处理(`try`, `except`, `else`, `finally`)
|
||||||
|
|
||||||
|
Python 中处理异常的关键字有四个:`try`、`except`、`finally`、`else`。
|
||||||
|
|
||||||
|
- `try`: 将可能引发异常的代码放在 `try` 块中。
|
||||||
|
- `except`: 当 `try` 块中的代码引发异常时,执行 `except` 块中的代码。可指定要捕获的异常类型。一个 `try` 块可以跟随多个 `except` 块,以捕获不同类型的异常。
|
||||||
|
- `finally`: 不论 `try` 块是否引发异常,都会执行 `finally` 块。常用于清理操作,如关闭文件。
|
||||||
|
- `else`: 若 `try` 块中无异常发生,则执行 `else` 块。`else` 是可选的。
|
||||||
|
|
||||||
|
```Python
|
||||||
|
try:
|
||||||
|
# 可能抛出异常的代码
|
||||||
|
result = 10 / 0
|
||||||
|
except ZeroDivisionError:
|
||||||
|
# 处理ZeroDivisionError异常的代码
|
||||||
|
print("Cannot divide by zero!")
|
||||||
|
else:
|
||||||
|
# try代码块成功执行后的代码
|
||||||
|
print("Operation successful.")
|
||||||
|
finally:
|
||||||
|
# 无论是否发生异常都会执行的代码
|
||||||
|
print("This is the finally block.")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Python 内置标准异常
|
||||||
|
|
||||||
|
| 异常名 | 描述 |
|
||||||
|
| --------------------- | ------------------------------------- |
|
||||||
|
| `BaseException` | **所有异常的基类** |
|
||||||
|
| `SystemExit` | 解释器请求退出 |
|
||||||
|
| `KeyboardInterrupt` | 用户中断执行 (通常是输入^C) |
|
||||||
|
| `Exception` | **常规错误的基类** |
|
||||||
|
| `StopIteration` | 迭代器没有更多的值 |
|
||||||
|
| `GeneratorExit` | 生成器 (generator) 发生异常来通知退出 |
|
||||||
|
| `SystemError` | 解释器发现内部错误 |
|
||||||
|
| `SyntaxError` | Python 语法错误 |
|
||||||
|
| `IndentationError` | 缩进错误 |
|
||||||
|
| `TabError` | Tab 和空格混用 |
|
||||||
|
| `NameError` | 未声明/初始化对象 (没有属性) |
|
||||||
|
| `UnboundLocalError` | 访问未初始化的本地变量 |
|
||||||
|
| `AttributeError` | 对象没有这个属性 |
|
||||||
|
| `TypeError` | 对类型无效的操作 |
|
||||||
|
| `AssertionError` | 断言语句失败 |
|
||||||
|
| `ImportError` | 导入模块/对象失败 |
|
||||||
|
| `ModuleNotFoundError` | 找不到模块 |
|
||||||
|
| `LookupError` | 无效数据查询的基类 |
|
||||||
|
| `IndexError` | 序列中没有此索引 (index) |
|
||||||
|
| `KeyError` | 映射中没有这个键 |
|
||||||
|
| `ValueError` | 传入无效的参数 |
|
||||||
|
| `UnicodeError` | Unicode 相关的错误 |
|
||||||
|
| `ArithmeticError` | 数学运算基类 |
|
||||||
|
| `FloatingPointError` | 浮点计算错误 |
|
||||||
|
| `OverflowError` | 数值运算超出最大限制 |
|
||||||
|
| `ZeroDivisionError` | 除 (或取模) 零 (所有数据类型) |
|
||||||
|
| `EnvironmentError` | 操作系统错误的基类 |
|
||||||
|
| `IOError` | 输入/输出操作失败 |
|
||||||
|
| `OSError` | 操作系统错误 |
|
||||||
|
| `EOFError` | 没有内建输入,到达 EOF 标记 |
|
||||||
|
| `RuntimeError` | 一般的运行时错误 |
|
||||||
|
| `NotImplementedError` | 尚未实现的方法 |
|
||||||
|
| `RecursionError` | 超过最大递归深度 |
|
||||||
|
|
||||||
|
## 自定义异常的创建和抛出
|
||||||
|
|
||||||
|
**自定义异常通过继承 `Exception` 类来定义。**在自定义类中,可以定义所需的任何方法,但通常自定义异常很简单,只提供基本信息。
|
||||||
|
|
||||||
|
要抛出自定义异常,使用 `raise` 关键字。在 `raise` 语句后,指定异常类型和可选的错误消息。
|
||||||
|
|
||||||
|
```Python
|
||||||
|
class CustomError(Exception):
|
||||||
|
"""自定义的异常类型"""
|
||||||
|
|
||||||
|
def __init__(self, message):
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
try:
|
||||||
|
raise CustomError("This is a custom error.")
|
||||||
|
except CustomError as e:
|
||||||
|
print("Caught an exception:", e.message)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 异常链(`raise from`)和异常上下文
|
||||||
|
|
||||||
|
Python 3 引入异常链允许在处理异常时引发另一个异常,保留原始异常的上下文。使用 `raise from` 实现。
|
||||||
|
|
||||||
|
```python
|
||||||
|
try:
|
||||||
|
int('a')
|
||||||
|
except ValueError as e:
|
||||||
|
raise RuntimeError('转换错误') from e
|
||||||
|
```
|
||||||
|
|
||||||
|
## 警告(`warnings` 模块)的实用场景
|
||||||
|
|
||||||
|
警告不中断程序,但提供有关潜在问题的信息。`warnings` 模块发出警告并处理。使用警告来通知即将废弃的功能,或提醒用户注意非关键问题。
|
||||||
|
|
||||||
|
```python
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
def my_function():
|
||||||
|
warnings.warn("这个功能即将废弃", DeprecationWarning)
|
||||||
|
|
||||||
|
my_function()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 异常处理最佳实践
|
||||||
|
|
||||||
|
### 合适的异常处理策略
|
||||||
|
|
||||||
|
- **确切地知道你在捕获什么**:仅捕获能正确处理的异常。
|
||||||
|
- **避免捕获太广泛的异常**:避免使用空 `except:` 子句,以免捕获所有异常。
|
||||||
|
- **在正确的层级处理异常**:在适当的抽象级别处理异常,避免在函数内部处理应由调用者处理的异常。
|
||||||
|
|
||||||
|
### 避免常见错误
|
||||||
|
|
||||||
|
- **过度使用异常处理**:不要使用异常处理来控制正常程序流程。
|
||||||
|
- **在异常处理中隐藏错误**:捕获异常时应记录或报告错误信息。
|
||||||
|
- **错误地屏蔽异常**:避免在 `except` 块中引发新异常,覆盖原始异常。
|
||||||
|
|
||||||
|
## 异常处理示例:网络应用程序
|
||||||
|
|
||||||
|
在网络应用程序中,需要从远程服务器获取数据。这可能因多种原因失败,如网络问题或服务器错误。使用异常处理优雅地处理这些问题,并提供回退机制或错误信息。
|
||||||
|
|
||||||
|
```python
|
||||||
|
import requests
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get('https://example.com/data')
|
||||||
|
response.raise_for_status()
|
||||||
|
except requests.exceptions.HTTPError as he:
|
||||||
|
print(f'HTTP错误: {he}')
|
||||||
|
except requests.exceptions.ConnectionError as ce:
|
||||||
|
print(f'连接错误: {ce}')
|
||||||
|
except requests.exceptions.Timeout as te:
|
||||||
|
print(f'请求超时: {te}')
|
||||||
|
else:
|
||||||
|
# 处理成功的响应
|
||||||
|
process_data(response)
|
||||||
|
```
|
||||||
|
|
||||||
|
在这个例子中,使用 [requests HTTP 库](Tech/programming-language/Python/模块/网络处理/requests%20HTTP%20库.md) 分别处理了 HTTP 错误、连接错误和超时错误,每种类型的错误都有专门的异常类。这使得错误处理更加具体和有用。
|
Loading…
Reference in New Issue
Block a user