Python如何以规范写法在try块if else条件成立时触发except块
结论
手动抛异常的实现思路完全可行,你写的核心逻辑能跑通,但存在几处不规范的地方,修正后就可以稳定使用。
现有代码的问题说明
- 异常捕获顺序错误:Python的异常匹配是从上到下执行的,
ConnectionError、SSLError本身就是Exception的子类,你把父类Exception放在异常元组最前面,会直接接住所有抛出的异常,后面两个具体异常类型永远不会被匹配到,属于不规范写法。 - 参数冗余:函数定义时声明了
record_url入参,但实际发请求时用了硬编码的固定URL,这个参数没有被使用,属于无效参数。 - 返回值类型不统一:请求成功时返回
response对象,重试耗尽时返回字符串'Con error',调用方如果不加类型判断直接处理返回值,很容易触发属性错误之类的问题。 - 异常类型太泛:手动抛出的是通用
Exception,后续如果要区分不同错误类型做特殊处理(比如4xx客户端错误不重试、5xx服务端错误才重试)会很难扩展。
修正后的参考代码
from time import sleep from random import randint from requests.exceptions import ConnectionError, SSLError class BadResponseCodeError(Exception): """自定义响应状态码异常,用于区分非2xx的错误场景""" pass def retries(scraper, json, headers, record_url, tries=10): for i in range(tries): try: response = scraper.post(record_url, json=json, headers=headers) if response.ok: print('请求成功,状态码正常') return response else: print(f'响应状态码异常,响应内容:{str(response)}') # 手动抛出自定义异常,触发后续重试逻辑 raise BadResponseCodeError(f"异常状态码:{response.status_code}") except (ConnectionError, SSLError, BadResponseCodeError) as e: print(f'第{i+1}次请求失败,错误信息:{str(e)}') if i < tries - 1: sleep(randint(1, 2)) continue # 重试耗尽后直接抛出明确异常,比返回字符串更稳妥 raise RuntimeError(f"重试{tries}次后仍然请求失败") from e
逻辑说明
- 自定义专门的响应码异常,和网络类异常放在同一个捕获列表里,非2xx场景下手动抛出这个异常,就会自动走到和连接错误、SSL错误完全一致的重试流程,完全匹配你的需求。
- 异常捕获把具体的子类放在前面,不会出现匹配失效的问题。
- 去掉了硬编码的URL,改用传入的
record_url参数,避免无效入参。 - 重试耗尽后直接抛出异常,而不是返回字符串,调用方可以统一用异常捕获的方式处理请求失败的场景,不会出现类型不统一的问题。
- 增加了必要的错误日志打印,排查问题时能明确知道每次失败的原因是连接问题、SSL问题还是状态码异常。
内容的提问来源于stack exchange,提问作者Rivered
相关产品推荐
相关产品推荐

