如何为调用requests.get的Python函数添加自定义装饰器?
实现方案:用装饰器临时替换
requests.get 核心思路是在被装饰函数执行的生命周期内,临时替换requests.get为预先包装好的版本,执行完函数后立刻恢复原方法——这样既不用修改任何现有requests.get调用,也不会影响全局范围内的requests.get使用。
具体实现
基础版装饰器
import requests from functools import wraps def my_custom_decorator(func): @wraps(func) def wrapper(*args, **kwargs): # 保存原始的requests.get方法 original_get = requests.get # 定义包装后的get方法,添加通用参数 def wrapped_get(url, **get_kwargs): # 这里可以定义你需要的通用参数 default_params = { "timeout": 15, "headers": {"User-Agent": "CustomBot/1.0"}, "verify": False # 示例:关闭SSL验证(根据需求调整) } # 用户传入的参数会覆盖默认值,保证灵活性 merged_kwargs = {**default_params, **get_kwargs} return original_get(url, **merged_kwargs) # 替换requests.get requests.get = wrapped_get try: # 执行被装饰的原函数 result = func(*args, **kwargs) finally: # 无论函数执行成功/失败,都恢复原始get方法 requests.get = original_get return result return wrapper
使用示例
@my_custom_decorator def hello(): # 这里的requests.get会自动带上我们定义的通用参数 resp = requests.get("https://example.com") print(f"状态码: {resp.status_code}") hello()
进阶优化:用上下文管理器分离逻辑
如果需要在多个地方复用替换逻辑,可以把替换/恢复的代码封装成上下文管理器,让装饰器代码更简洁:
import requests from functools import wraps from contextlib import contextmanager @contextmanager def override_requests_get(): original_get = requests.get def wrapped_get(url, **get_kwargs): default_params = { "timeout": 15, "headers": {"User-Agent": "CustomBot/1.0"} } merged_kwargs = {**default_params, **get_kwargs} return original_get(url, **merged_kwargs) requests.get = wrapped_get try: yield finally: requests.get = original_get # 装饰器复用上下文管理器 def my_custom_decorator(func): @wraps(func) def wrapper(*args, **kwargs): with override_requests_get(): return func(*args, **kwargs) return wrapper
为什么比检查函数内容更优
你之前考虑的检查函数是否包含requests.get的方法存在明显缺陷:
- 静态扫描代码字符串无法覆盖所有情况:比如函数内用了
from requests import get、间接调用(比如通过其他函数封装的get),都会漏判。 - 容易出现误判:比如函数里只是字符串提到了
requests.get,并非实际调用。
而临时替换的方法是运行时动态拦截,只要函数在执行期间调用了requests.get,就会被我们的包装方法接管,完全覆盖所有调用场景,且对原代码零侵入。
内容的提问来源于stack exchange,提问作者xan
相关产品推荐
相关产品推荐

