如何让Python警告显示插件status方法的文件路径及行号?
解决方案
核心思路
要让警告精准指向插件中status方法的定义位置,同时保证每个插件文件仅提示一次,且兼容原生警告过滤,需要结合inspect模块获取方法定义信息,使用warnings.warn_explicit()手动指定警告位置,并通过全局集合实现去重。
实现步骤与代码示例
1. 驱动类(Driver)核心代码
import warnings import inspect # 记录已触发警告的插件文件,避免重复提示 _warned_plugin_files = set() class Driver: def run_plugin_status(self, plugin): status_result = plugin.status() # 检查返回值是否为即将弃用的dict类型 if isinstance(status_result, dict): status_method = plugin.status try: # 获取status方法的定义文件和行号 method_file = inspect.getsourcefile(status_method) method_lineno = inspect.getsourcelines(status_method)[1] except (TypeError, OSError): # 无法获取源码时,回退到默认警告逻辑 warnings.warn( "插件status方法返回dict格式已弃用,请改为返回list格式", PendingDeprecationWarning, stacklevel=2 ) return status_result # 仅对未警告过的文件触发提示 if method_file not in _warned_plugin_files: _warned_plugin_files.add(method_file) # 手动指定警告的位置信息 warnings.warn_explicit( message="插件status方法返回dict格式已弃用,请改为返回list格式", category=PendingDeprecationWarning, filename=method_file, lineno=method_lineno, module=plugin.__module__ ) return status_result
2. 插件示例(p0.py)
class DemoPlugin: def status(self): # 此方法返回dict,警告会精准指向该行 return {"state": "running"}
3. 测试与效果
from p0 import DemoPlugin from driver import Driver driver = Driver() # 第一次调用,触发警告,指向p0.py中status方法的定义行 driver.run_plugin_status(DemoPlugin()) # 第二次调用,不会重复弹出警告 driver.run_plugin_status(DemoPlugin())
关键细节说明
- 精准定位警告位置:通过
inspect模块获取插件status方法的源码文件和行号,再用warnings.warn_explicit()手动传入这些信息,让警告直接指向需要修改的代码位置。 - 避免重复警告:用全局集合
_warned_plugin_files记录已触发警告的文件路径,确保每个插件文件仅提示一次。 - 兼容原生警告过滤:抛出标准的
PendingDeprecationWarning,用户可通过常规方式屏蔽警告:
或通过命令行参数:# 代码中过滤警告 warnings.filterwarnings("ignore", category=PendingDeprecationWarning)python -W ignore::PendingDeprecationWarning your_script.py - 异常回退:当无法获取插件方法的源码信息(如内置方法、C扩展)时,自动回退到
warnings.warn()并设置stacklevel=2,保证警告信息仍有参考价值。
内容的提问来源于stack exchange,提问作者Anthon
相关产品推荐
相关产品推荐

