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 导入顺序 标准库导入 第三方库导入(如 pip 安装的包) 本地应用/库特定导入 4.3 导入格式 每行只导入一个模块:import os 和 import sys 而不是 import os, sys。 从包中导入多个类时,每行只导入一个:from mypackage import Class1 和 from 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:语句,因为这会捕获包括KeyboardInterrupt和SystemExit在内的所有异常。
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 : result = risky_operation() process_result(result) save_to_database(result) except Exception as e: log_error(e) 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: 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 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 logginglogger = 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} " )
2.2 捕获多个异常类型 1 2 3 4 5 6 7 8 9 10 11 12 13 try : value = int ("abc" ) except ValueError as e: print (f"值转换错误: {e} " ) except TypeError as e: print (f"类型错误: {e} " ) 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 : 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 : 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 try : risky_operation() except : print ("发生错误" ) try : risky_operation() except (ValueError, TypeError, IOError) as e: print (f"操作失败: {e} " ) try : safe_operation() except Exception: pass import logginglogger = 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 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 requestsimport loggingfrom requests.exceptions import RequestException, Timeout, ConnectionErrorlogger = logging.getLogger(__name__) def fetch_data (url, timeout=10 ): """安全的网络请求函数""" try : response = requests.get(url, timeout=timeout) response.raise_for_status() 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: 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 sqlite3from 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. 关键要点总结 捕获特定异常 :总是捕获具体的异常类型,避免使用裸露的 except:资源管理 :使用 with 语句或 finally 块确保资源正确释放异常链 :使用 raise from 保留原始异常信息日志记录 :在捕获异常时记录详细信息,包括堆栈跟踪适当传播 :在底层捕获并记录异常后,考虑重新抛出或转换为业务异常避免空处理 :不要默默地忽略异常,至少要记录下来使用异常类层次 :为应用程序定义自定义异常类层次结构性能考虑 :异常处理开销较大,不应在正常控制流中频繁使用通过遵循这些模式和最佳实践,可以构建健壮、可维护的 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: print (f"系统错误: {e} " ) except LookupError as e: 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 jsonimport osfrom configparser import ConfigParser, Error as ConfigErrordef 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 requestsfrom 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() 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. 关键要点总结 捕获顺序很重要 :从具体到一般,避免被前面的 except 块捕获避免裸露的 except :总是捕获具体的异常类型使用异常对象 :通过 as e 获取异常对象,访问详细信息合理分组 :将需要相同处理逻辑的异常分组捕获异常层次 :利用 Python 的异常层次结构进行高效捕获资源清理 :始终使用 finally 或 with 语句确保资源释放日志记录 :在捕获异常时记录详细信息,便于调试重新抛出 :在适当的时候重新抛出异常,保持调用栈完整性通过合理选择异常处理策略,可以使代码更加健壮、可维护,并提供更好的错误诊断能力。
**主要修复内容:**
1. 统一标题层级,使用合理的层次结构(## → 3. → 3.1 → 3.1.1)
2. 修复所有代码块嵌套错误,移除代码块内多余的```标记
3. 统一列表格式,确保缩进一致
4. 为所有代码块添加正确的语言标识
5. 规范段落间距和格式
6. 保持所有内容完整不变