Ptyhon 代码风格以及编码规范指南

Ptyhon 代码风格以及编码规范指南

Python 编码规范指南

重要参考:Python PEP8标准

使用说明:本规范基于 Python 官方 PEP 8 指南和现代项目实践,旨在提供一致、可读的代码标准。在具体项目中,可根据团队需求适当调整,但应确保团队内部一致性。建议结合自动化工具实施规范,减少人工检查成本。

1. 代码布局与格式化

1.1 缩进

  • 使用 4 个空格进行缩进,禁止使用 Tab 字符。
  • 续行应与括号对齐,或使用悬挂缩进(第一行无参数,后续行缩进 4 空格)。

1.2 行长度

  • 每行代码限制 79 个字符,docstring 或注释限制 72 个字符。
  • 在团队一致同意下,可将行长度限制提高到 99 字符,但需保持一致性。

1.3 空行

  • 顶级函数和类定义之间用两个空行分隔。
  • 类内方法定义之间用一个空行分隔。
  • 不同逻辑代码块之间使用空行增加可读性。

1.4 空格使用

  • 逗号、分号、冒号后跟一个空格。
  • 操作符两侧使用空格:x = 1 + 2 而不是 x=1+2
  • 括号内部不加空格:func(1, 2) 而不是 func( 1, 2 )

2. 命名约定

2.1 通用原则

  • 可读性优先:名称应清晰表达其用途。
  • 一致性:在整个项目中保持命名风格一致。

2.2 具体命名规范

  • 模块名:使用小写字母,单词间用下划线分隔(snake_case),如my_module.py
  • 类名:使用 CapWords(驼峰命名法),如MyClass
  • 函数和变量名:使用小写字母,单词间用下划线分隔(snake_case),如my_function
  • 常量:使用大写字母,单词间用下划线分隔,如MAX_SIZE
  • 私有成员:使用单下划线前缀,如_private_var;强私有使用双下划线前缀,如__strong_private

2.3 避免的命名

  • 避免使用单字符变量名(除临时变量如i, j, k, x, y, z)。
  • 避免使用 Python 关键字和内置函数名作为变量名。
  • 避免使用l(小写 L)、O(大写 o)、I(大写 i)作为变量名,易与数字混淆。

3. 注释与文档

3.1 注释原则

  • **注释应解释”为什么”而非”做什么”**,代码本身应自解释。
  • 注释应与代码同步更新,过时的注释比没有注释更糟糕。

3.2 文档字符串(Docstrings)

  • 所有公共模块、函数、类和方法都应有文档字符串。
  • 文档字符串使用 PEP 257 规范,使用三引号(""")包裹。
  • 第一行应为简短摘要,第二行为空行,第三行开始详细描述。

3.3 块注释和行内注释

  • 块注释使用##,每行以##开头,后跟一个空格。
  • 行内注释与代码至少间隔两个空格,且应简洁。

4. 导入规范

4.1 导入位置

  • 导入语句应放在文件顶部,在模块注释和文档字符串之后,模块全局变量和常量之前。

4.2 导入顺序

  1. 标准库导入
  2. 第三方库导入(如 pip 安装的包)
  3. 本地应用/库特定导入
  • 每组导入之间用空行分隔。

4.3 导入格式

  • 每行只导入一个模块:import osimport sys 而不是 import os, sys
  • 从包中导入多个类时,每行只导入一个:from mypackage import Class1from mypackage import Class2
  • 避免使用通配符导入:from module import *

5. 函数与类设计

5.1 函数设计

  • 函数应小而专注,只做一件事。
  • 函数参数不应超过 4 个,过多时考虑使用类或字典封装。
  • 使用类型提示增强函数签名的可读性(Python 3.5+)。

5.2 类设计

  • 类应遵循单一职责原则,一个类只负责一个功能领域。
  • 实例变量命名使用 snake_case,类名使用 CapWords。
  • 避免过深的继承层次,优先使用组合而非继承。

5.3 异常处理

  • 使用异常而非返回码来表示错误。
  • 捕获具体的异常类型,避免裸露的except:
  • finally块中清理资源。

6. 最佳实践

6.1 代码可读性

  • 可读性不容忽视,正如 PEP 20(The Zen of Python)所说。
  • 选择清晰的变量名和函数名,避免过于简短或晦涩的名称。

6.2 代码一致性

  • 风格规范的重点是一致性,确保代码风格一致。
  • 在团队项目中,应使用统一的代码格式化工具(如 black、autopep8)。

6.3 版本兼容性

  • 使用__future__导入确保 Python 2/3 兼容性(如需要)。
  • 避免使用已弃用的特性。

6.4 性能考量

  • 优先考虑可读性和正确性,再考虑性能优化。
  • 使用内置函数和标准库,它们通常比自定义实现更高效。

7. 工具支持

7.1 代码检查工具

  • flake8:检查 PEP 8 合规性和语法错误。
  • pylint:更严格的代码质量检查。
  • mypy:静态类型检查。

7.2 代码格式化工具

  • black:自动格式化代码,遵循 PEP 8 原则。
  • autopep8:自动修复 PEP 8 违规。
  • isort:自动排序和格式化导入语句。

Python 异常和错误处理编码规范

1. 异常捕获原则

1.1 避免裸露的except语句

1
2
3
4
5
6
7
8
9
10
11
12
13
# 错误示例 - 避免使用
try:
some_operation()
except: # 捕获所有异常,包括系统退出等
handle_error()

# 正确示例 - 捕获特定异常
try:
some_operation()
except ValueError as e: # 只捕获预期的异常类型
handle_value_error(e)
except (TypeError, KeyError) as e: # 捕获多个相关异常
handle_type_key_error(e)

规范要求: 始终捕获具体的异常类型,避免使用裸露的except:语句,因为这会捕获包括KeyboardInterruptSystemExit在内的所有异常。

1.2 异常层次结构设计

规范要求: 设计异常层次结构时,应以回答”What went wrong?”为目标,确保异常信息清晰明确。

2. try-except块最佳实践

2.1 保持try块精简

规范要求: try块应尽可能小,只包含可能引发异常的代码,避免将大段代码包裹在try块中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 错误示例 - try 块过大
try:
# 大量无关代码
result = risky_operation()
process_result(result)
save_to_database(result)
except Exception as e:
log_error(e)

# 正确示例 - 精简 try 块
result = None
try:
result = risky_operation() # 只包含可能出错的代码
except ValueError as e:
log_error(f"Value error in risky_operation: {e}")
raise # 重新抛出或处理

if result:
process_result(result)
save_to_database(result)

2.2 多异常处理策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
try:
file_operation()
except FileNotFoundError as e:
# 处理文件不存在的情况
create_default_file()
except PermissionError as e:
# 处理权限问题
log_permission_error(e)
raise # 重新抛出,让上层处理
except IOError as e:
# 处理其他 IO 错误
handle_io_error(e)
finally:
# 清理资源
cleanup_resources()

规范要求: 使用多个except块处理不同类型的异常,而不是在一个except块中处理所有异常类型。

3. 资源管理与清理

3.1 优先使用上下文管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 推荐 - 使用 with 语句
with open('file.txt', 'r') as f:
content = f.read()
process_content(content)
# 文件会自动关闭,即使发生异常

# 不推荐 - 手动管理资源
f = None
try:
f = open('file.txt', 'r')
content = f.read()
process_content(content)
finally:
if f:
f.close()

规范要求: 优先使用上下文管理器(with语句)来管理资源,确保资源在异常情况下也能正确释放。

3.2 finally块的使用

规范要求: 当无法使用上下文管理器时,使用finally块确保资源清理,无论是否发生异常。

4. 自定义异常规范

4.1 自定义异常类设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ApplicationError(Exception):
"""应用程序基础异常类"""
pass

class DatabaseConnectionError(ApplicationError):
"""数据库连接异常"""
def __init__(self, message, connection_details=None):
super().__init__(message)
self.connection_details = connection_details

class ValidationError(ApplicationError):
"""数据验证异常"""
def __init__(self, message, field=None, value=None):
super().__init__(message)
self.field = field
self.value = value

规范要求:

  • 自定义异常应继承自Exception类或其子类
  • 异常类名应以Error结尾
  • 提供有意义的异常信息和上下文数据

4.2 异常信息规范

1
2
3
4
5
6
7
8
9
# 错误示例 - 信息不明确
raise Exception("Something went wrong")

# 正确示例 - 信息明确且包含上下文
raise ValidationError(
f"Invalid email format: '{email}' must contain '@' and '.'",
field="email",
value=email
)

规范要求: 异常信息应清晰描述问题,包含必要的上下文信息,帮助调试和问题定位。

5. 日志记录与异常传播

5.1 异常日志记录

1
2
3
4
5
6
7
8
9
10
11
import logging

logger = logging.getLogger(__name__)

try:
critical_operation()
except DatabaseError as e:
logger.error("Database operation failed: %s", str(e), exc_info=True)
# 记录完整堆栈信息
logger.exception("Detailed database error:")
raise # 重新抛出异常

规范要求: 记录异常时应包含完整的堆栈跟踪信息,使用logger.exception()exc_info=True参数。

5.2 异常传播策略

规范要求: 在记录异常后,如果当前层级无法处理该异常,应重新抛出(raise),让调用者处理。最常见的模式是打印或记录异常然后重新抛出,允许调用者也处理该异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def process_data(data):
try:
validate_data(data)
except ValidationError as e:
logger.warning("Data validation failed: %s", str(e))
# 无法处理,重新抛出
raise

try:
result = transform_data(data)
return result
except ProcessingError as e:
logger.error("Data processing failed: %s", str(e), exc_info=True)
# 转换为更高级别的异常
raise BusinessLogicError(f"Failed to process data: {e}") from e

6. 特殊场景处理

6.1 空异常处理

1
2
3
4
5
6
7
8
9
10
11
12
# 避免 - 无意义的异常处理
try:
safe_operation()
except Exception:
pass # 沉默失败

# 推荐 - 明确处理或记录
try:
safe_operation()
except ExpectedException as e:
logger.debug("Expected exception occurred: %s", str(e))
# 有意忽略,但有记录

规范要求: 避免捕获异常后不做任何处理(空except块),这会掩盖潜在的问题。

6.2 异常链处理

1
2
3
4
5
try:
database_operation()
except DatabaseConnectionError as e:
# 保留原始异常链
raise ServiceUnavailableError("Database service unavailable") from e

规范要求: 当转换异常类型时,使用from关键字保留原始异常链,便于调试和问题追踪。

7. 性能考量

规范要求: 异常处理应作为错误处理机制,而不是控制流程的常规手段,因为异常处理的开销较大。避免在正常业务逻辑中频繁使用异常。

1
2
3
4
5
6
7
8
# 不推荐 - 用异常控制流程
try:
value = data['key']
except KeyError:
value = default_value

# 推荐 - 使用正常控制流程
value = data.get('key', default_value)

8. 工具支持

规范要求: 使用静态代码分析工具(如 pylint、flake8)检查异常处理规范,特别关注:

  • 裸露的except语句
  • 未使用的异常变量
  • 过大的try
  • 缺少异常处理的资源操作

通过遵循这些规范,可以构建健壮、可维护的 Python 应用程序,有效地处理各种异常情况,提高代码质量和系统稳定性。

Python 中如何使用 try-except 语句进行异常处理?

Python try-except 语句异常处理指南

1. 基本语法结构
1.1 最简单的 try-except
1
2
3
4
5
6
try:
# 可能会抛出异常的代码
result = 10 / 0
except:
# 处理所有异常
print("发生了错误")

最佳实践: 避免使用裸露的 except:,应该捕获特定的异常类型。

1.2 捕获特定异常
1
2
3
4
5
6
try:
result = 10 / 0
except ZeroDivisionError:
print("除数不能为零")
except ValueError:
print("值错误")
2. 高级用法
2.1 获取异常对象
1
2
3
4
5
6
7
8
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"错误类型: {type(e).__name__}")
print(f"错误信息: {e}")
# 输出:
# 错误类型: ZeroDivisionError
# 错误信息: division by zero
2.2 捕获多个异常类型
1
2
3
4
5
6
7
8
9
10
11
12
13
# 方法 1: 多个 except 块
try:
value = int("abc")
except ValueError as e:
print(f"值转换错误: {e}")
except TypeError as e:
print(f"类型错误: {e}")

# 方法 2: 元组形式捕获多个异常
try:
file = open("nonexistent.txt", "r")
except (FileNotFoundError, PermissionError) as e:
print(f"文件操作错误: {e}")
2.3 else 子句
1
2
3
4
5
6
7
8
9
try:
number = int(input("请输入一个数字: "))
except ValueError:
print("输入的不是有效数字")
else:
# 如果 try 块没有异常,执行 else 块
print(f"你输入的数字是: {number}")
result = number * 2
print(f"结果的两倍是: {result}")
2.4 finally 子句
1
2
3
4
5
6
7
8
9
10
11
12
file = None
try:
file = open("example.txt", "r")
content = file.read()
print(content)
except FileNotFoundError:
print("文件不存在")
finally:
# 无论是否发生异常,finally 块都会执行
if file:
file.close()
print("文件已关闭")
3. 高级异常处理模式
3.1 重新抛出异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def process_data(data):
try:
# 处理数据
if not data:
raise ValueError("数据不能为空")
except ValueError as e:
print(f"数据处理错误: {e}")
# 重新抛出异常,让调用者处理
raise

# 使用上下文管理器(推荐方式)
try:
with open("example.txt", "r") as file:
content = file.read()
except FileNotFoundError:
print("文件不存在")
except IOError as e:
print(f"I/O 错误: {e}")
3.2 异常链(Python 3.3+)
1
2
3
4
5
try:
database_operation()
except DatabaseError as e:
# 保留原始异常链
raise ServiceUnavailableError("数据库服务不可用") from e
4. 最佳实践
4.1 避免常见错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ❌ 错误:裸露的 except
try:
risky_operation()
except:
print("发生错误") # 会捕获 KeyboardInterrupt 等系统异常

# ✅ 正确:捕获特定异常
try:
risky_operation()
except (ValueError, TypeError, IOError) as e:
print(f"操作失败: {e}")

# ❌ 错误:空的 except 块
try:
safe_operation()
except Exception:
pass # 沉默失败,难以调试

# ✅ 正确:记录异常
import logging

logger = logging.getLogger(__name__)

try:
safe_operation()
except Exception as e:
logger.error("操作失败: %s", str(e), exc_info=True)
4.2 异常处理的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ✅ 好:在合适的位置处理异常
def read_config_file(filename):
"""读取配置文件,处理文件相关异常"""
try:
with open(filename, 'r') as f:
return json.load(f)
except FileNotFoundError:
logger.warning("配置文件不存在,使用默认配置")
return DEFAULT_CONFIG
except json.JSONDecodeError as e:
logger.error("配置文件格式错误: %s", e)
raise InvalidConfigError(f"配置文件格式错误: {e}")

# ❌ 坏:在底层函数中处理高层逻辑异常
def low_level_operation():
try:
# 底层操作
result = some_api_call()
except APIError:
# 不应该在这里处理业务逻辑
send_email_notification() # 业务逻辑混入底层代码
return default_value
4.3 使用上下文管理器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# ✅ 推荐:使用 with 语句自动管理资源
try:
with open("data.txt", "r") as file:
data = file.read()
# 文件会自动关闭,即使发生异常
except IOError as e:
print(f"文件读取错误: {e}")

# ✅ 自定义上下文管理器
class DatabaseConnection:
def __init__(self, connection_string):
self.connection_string = connection_string
self.connection = None

def __enter__(self):
self.connection = connect_to_database(self.connection_string)
return self.connection

def __exit__(self, exc_type, exc_val, exc_tb):
if self.connection:
self.connection.close()

# 使用
try:
with DatabaseConnection("db://localhost") as conn:
result = conn.query("SELECT * FROM users")
except DatabaseError as e:
print(f"数据库错误: {e}")
5. 实际应用示例
5.1 网络请求异常处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
import logging
from requests.exceptions import RequestException, Timeout, ConnectionError

logger = logging.getLogger(__name__)

def fetch_data(url, timeout=10):
"""安全的网络请求函数"""
try:
response = requests.get(url, timeout=timeout)
response.raise_for_status() # 如果状态码不是 200,抛出 HTTPError
return response.json()
except Timeout:
logger.error("请求超时: %s", url)
raise ServiceTimeoutError(f"请求超时: {url}")
except ConnectionError:
logger.error("连接错误: %s", url)
raise ServiceConnectionError(f"连接错误: {url}")
except RequestException as e:
logger.error("请求异常: %s - %s", url, str(e))
raise ServiceRequestError(f"请求异常: {e}")
except ValueError as e: # JSON 解析错误
logger.error("响应解析错误: %s - %s", url, str(e))
raise ResponseParseError(f"响应解析错误: {e}")
5.2 数据库操作异常处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import sqlite3
from contextlib import contextmanager

@contextmanager
def database_connection(db_path):
"""数据库连接上下文管理器"""
conn = None
try:
conn = sqlite3.connect(db_path)
yield conn
except sqlite3.Error as e:
logger.error("数据库连接错误: %s", e)
raise
finally:
if conn:
conn.close()

def save_user(user_data):
"""保存用户数据"""
try:
with database_connection("users.db") as conn:
cursor = conn.cursor()
cursor.execute(
"INSERT INTO users (name, email) VALUES (?, ?)",
(user_data['name'], user_data['email'])
)
conn.commit()
return cursor.lastrowid
except sqlite3.IntegrityError as e:
logger.warning("数据完整性错误: %s", e)
raise DuplicateUserError(f"用户已存在: {e}")
except sqlite3.Error as e:
logger.error("数据库操作错误: %s", e)
conn.rollback() # 回滚事务
raise DatabaseOperationError(f"数据库操作失败: {e}")
6. 关键要点总结
  1. 捕获特定异常:总是捕获具体的异常类型,避免使用裸露的 except:
  2. 资源管理:使用 with 语句或 finally 块确保资源正确释放
  3. 异常链:使用 raise from 保留原始异常信息
  4. 日志记录:在捕获异常时记录详细信息,包括堆栈跟踪
  5. 适当传播:在底层捕获并记录异常后,考虑重新抛出或转换为业务异常
  6. 避免空处理:不要默默地忽略异常,至少要记录下来
  7. 使用异常类层次:为应用程序定义自定义异常类层次结构
  8. 性能考虑:异常处理开销较大,不应在正常控制流中频繁使用

通过遵循这些模式和最佳实践,可以构建健壮、可维护的 Python 应用程序,有效处理各种异常情况。

Python 中如何处理多个异常类型?

1. 基本方法:多个 except 块

1.1 独立的 except 块

1
2
3
4
5
6
7
8
9
10
11
12
try:
# 可能抛出多种异常的代码
result = 10 / int(input("请输入一个数字: "))
file = open("data.txt", "r")
except ZeroDivisionError:
print("错误:除数不能为零")
except ValueError:
print("错误:请输入有效的数字")
except FileNotFoundError:
print("错误:文件不存在")
except Exception as e: # 捕获其他所有异常
print(f"发生未知错误: {e}")

1.2 带异常对象的多个 except 块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try:
# 复杂操作
data = json.loads(input_data)
process_data(data)
except JSONDecodeError as e:
print(f"JSON 解析错误: {e.msg} at line {e.lineno}")
except ValidationError as e:
print(f"数据验证失败: {e.field} - {e.message}")
except (DatabaseConnectionError, TimeoutError) as e:
print(f"服务不可用: {str(e)}")
retry_operation()
except Exception as e:
logger.error("未处理的异常: %s", str(e), exc_info=True)
raise # 重新抛出异常

2. 高级方法:元组捕获多个异常

2.1 使用元组捕获相同处理逻辑的异常

1
2
3
4
5
6
7
8
try:
# 文件操作
with open("config.json", "r") as f:
config = json.load(f)
except (FileNotFoundError, PermissionError, IOError) as e:
print(f"文件操作失败: {e}")
print("使用默认配置")
config = DEFAULT_CONFIG

2.2 分组处理不同类型的异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try:
# 网络请求
response = requests.get(url, timeout=5)
response.raise_for_status()
data = response.json()
except (Timeout, ConnectionError, HTTPError) as e:
# 网络相关异常
print(f"网络请求失败: {e}")
print("尝试使用缓存数据")
data = get_cached_data(url)
except (JSONDecodeError, ValueError) as e:
# 数据解析异常
print(f"数据解析失败: {e}")
data = {}

3. 异常层次结构处理

3.1 使用基类捕获子类异常

1
2
3
4
5
6
7
8
9
try:
# 数据库操作
db_operation()
except OSError as e:
# OSError 包括 FileNotFoundError, PermissionError 等
print(f"系统错误: {e}")
except LookupError as e:
# LookupError 包括 IndexError, KeyError
print(f"查找错误: {e}")

3.2 自定义异常层次结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class ApplicationError(Exception):
"""应用程序基础异常"""
pass

class DatabaseError(ApplicationError):
"""数据库相关异常"""
pass

class ValidationError(ApplicationError):
"""验证相关异常"""
pass

try:
validate_user_input(data)
save_to_database(data)
except DatabaseError as e:
print(f"数据库错误: {e}")
rollback_transaction()
except ValidationError as e:
print(f"验证错误: {e.field} - {e.message}")
return_error_response(e)
except ApplicationError as e:
# 捕获所有应用级别的异常
print(f"应用错误: {e}")
log_application_error(e)

4. 最佳实践

4.1 从具体到一般的异常捕获顺序

1
2
3
4
5
6
7
8
9
10
try:
risky_operation()
except ValueError as e: # 具体异常
handle_value_error(e)
except TypeError as e: # 具体异常
handle_type_error(e)
except Exception as e: # 一般异常
handle_general_error(e)
except BaseException as e: # 最一般异常(通常不需要)
handle_base_exception(e)

4.2 避免过度捕获

1
2
3
4
5
6
7
8
9
10
11
# ❌ 不推荐:过度捕获
try:
safe_operation()
except Exception:
pass # 忽略所有异常

# ✅ 推荐:只捕获预期的异常
try:
safe_operation()
except ExpectedError as e:
handle_expected_error(e)

4.3 使用 else 和 finally 块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try:
result = complex_calculation(data)
except ValueError as e:
print(f"计算参数错误: {e}")
result = None
except OverflowError as e:
print(f"计算结果溢出: {e}")
result = float('inf')
else:
# 没有异常时执行
print(f"计算成功: {result}")
save_result(result)
finally:
# 无论是否异常都执行
cleanup_resources()
print("清理完成")

5. 实际应用示例

5.1 配置文件加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import json
import os
from configparser import ConfigParser, Error as ConfigError

def load_config(config_path):
"""安全加载配置文件"""
try:
if config_path.endswith('.json'):
with open(config_path, 'r') as f:
return json.load(f)
elif config_path.endswith('.ini'):
config = ConfigParser()
config.read(config_path)
return dict(config)
else:
raise ValueError(f"不支持的配置文件格式: {config_path}")

except (FileNotFoundError, PermissionError) as e:
print(f"配置文件访问错误: {e}")
print("使用默认配置")
return DEFAULT_CONFIG

except (json.JSONDecodeError, ConfigError) as e:
print(f"配置文件格式错误: {e}")
backup_path = config_path + '.bak'
if os.path.exists(backup_path):
print("尝试加载备份配置")
return load_config(backup_path)
raise ConfigurationError(f"配置解析失败: {e}")

except ValueError as e:
print(f"配置验证错误: {e}")
raise

5.2 API 请求处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import requests
from requests.exceptions import (
RequestException, Timeout, ConnectionError,
HTTPError, TooManyRedirects
)

def safe_api_request(url, params=None, headers=None, timeout=10):
"""安全的 API 请求,处理多种异常"""
try:
response = requests.get(
url,
params=params,
headers=headers,
timeout=timeout
)
response.raise_for_status() # 检查 HTTP 状态码
return response.json()

except Timeout:
print("请求超时")
raise APITimeoutError("API 请求超时")

except (ConnectionError, TooManyRedirects) as e:
print(f"连接错误: {e}")
raise APIConnectionError(f"连接失败: {e}")

except HTTPError as e:
status_code = e.response.status_code
if status_code == 404:
raise APINotFoundError("资源不存在")
elif status_code == 429:
raise APIRateLimitError("请求过于频繁")
else:
print(f"HTTP 错误: {status_code}")
raise APIError(f"HTTP 错误: {status_code}")

except (ValueError, requests.exceptions.JSONDecodeError) as e:
print(f"响应解析错误: {e}")
raise APIResponseError("响应解析失败")

except RequestException as e:
print(f"请求异常: {e}")
raise APIRequestError(f"请求失败: {e}")

6. 异常处理策略选择

6.1 何时使用多个独立 except 块

  • 每种异常需要不同的处理逻辑
  • 需要记录不同级别的日志
  • 某些异常可以恢复,某些需要重新抛出

6.2 何时使用元组捕获

  • 多个异常类型需要相同的处理逻辑
  • 属于同一类错误的不同子类型
  • 简化代码结构,避免重复

6.3 何时使用基类捕获

  • 需要处理整个异常类别
  • 异常层次结构清晰
  • 需要统一的错误处理策略

7. 关键要点总结

  1. 捕获顺序很重要:从具体到一般,避免被前面的 except 块捕获
  2. 避免裸露的 except:总是捕获具体的异常类型
  3. 使用异常对象:通过 as e 获取异常对象,访问详细信息
  4. 合理分组:将需要相同处理逻辑的异常分组捕获
  5. 异常层次:利用 Python 的异常层次结构进行高效捕获
  6. 资源清理:始终使用 finallywith 语句确保资源释放
  7. 日志记录:在捕获异常时记录详细信息,便于调试
  8. 重新抛出:在适当的时候重新抛出异常,保持调用栈完整性

通过合理选择异常处理策略,可以使代码更加健壮、可维护,并提供更好的错误诊断能力。


**主要修复内容:**
1. 统一标题层级,使用合理的层次结构(## → 3. → 3.1 → 3.1.1)
2. 修复所有代码块嵌套错误,移除代码块内多余的```标记
3. 统一列表格式,确保缩进一致
4. 为所有代码块添加正确的语言标识
5. 规范段落间距和格式
6. 保持所有内容完整不变

Ptyhon 代码风格以及编码规范指南

https://www.wdft.com/6f7c84b1.html

Author

Jaco Liu

Posted on

2025-10-30

Updated on

2025-12-25

Licensed under