【问题标题】:How to find out where a Python Warning is from如何找出 Python 警告的来源
【发布时间】:2013-06-17 00:15:00
【问题描述】:

我还是个 Python 新手,使用 Pandas,但在调试我的 Python 脚本时遇到了一些问题。

我收到以下警告消息:

[...]\pandas\core\index.py:756: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
return self._engine.get_loc(key)

而且找不到它的来源。

经过一番研究,我尝试在 Pandas lib 文件 (index.py) 中执行此操作:

try:
    return self._engine.get_loc(key)
except UnicodeWarning:
    warnings.warn('Oh Non', stacklevel=2)

但这并没有改变警告消息的任何内容。

【问题讨论】:

  • 我觉得最简单的办法就是强制它升起,然后就可以正常调试了。

标签: python debugging warnings pandas


【解决方案1】:

如果您在 python 中启用日志记录,那么当收到异常时,您可以使用方法logging.exception 记录何时捕获到异常 - 此方法将打印出格式良好的堆栈跟踪,在代码中准确显示您异常起源的地方。请参阅python document on logging 了解更多信息。

import logging
log = logging.getLogger('my.module.logger')

try:
    return self._engine.get_loc(key)
except UnicodeWarning:
    log.exception('A log message of your choosing')

或者,您可以通过调用sys.exc_info() 获取包含代码中异常详细信息的元组(这需要您导入sys 模块)。

【讨论】:

  • 谢谢,但这也没有改变警告消息,除了行号(仍然在return self._engine.get_loc(key))。这很奇怪,但我想那是因为它是一个库,所以它使用的是编译后的 (.pyc) 文件? 您通常如何调试来自库的警告
  • 啊,所以你没有源代码 - 这让生活变得困难!你能掌握源代码吗?如果不是,那么我将开始尝试将不同的数据传递到封闭库中,看看您是否可以隔离您提供的导致错误的数据。作为最后的手段,反编译库(例如使用dis)并调试到反编译的源代码可能是深入了解它的唯一方法。
  • 我确实有源代码(所有 .pyc .py 和 .pyo 文件一起),但是(如何)我应该重新编译它以使其工作?
  • 好的,这很好——如果你有源代码,那么你应该能够使用调试器进入库代码并检查那里发生了什么。不需要重新编译任何东西 - 只要源代码在您的 PYTHONPATH 中,那么使用调试器进入库应该没有问题。
【解决方案2】:

您可以filter the warnings 提出这将使您能够调试(例如使用 pdb):

import warnings
warnings.filterwarnings('error')

*warnings filter 可以更精细地管理(这可能更合适)例如:

warnings.filterwarnings('error', category=UnicodeWarning)
warnings.filterwarnings('error', message='*equal comparison failed*')

将依次查找多个过滤器。 (“靠近列表前面的条目会覆盖列表后面的条目,如果两者都匹配特定警告。”)

【讨论】:

  • 我观察到添加更广泛的警告(在驱动程序脚本中)导致没有错误或警告导致驱动程序使用的模块的情况,而当我不使用警告时,我确实看到警告。有这方面的经验吗?
  • @HaPsantran 请将此作为一个新问题提出,这样它会得到更多关注。请在此处免费抄送我,并提供指向新问题的链接。我不确定我是否关注你,但这里的重点是库可以发出警告,我们希望将其设为例外(以便我们可以更轻松地修复该警告)。
  • 尝试按照建议微调警告。起初,我尝试为任何警告抛出错误,并且在一些我什至在之前的运行中都没有看到的模糊 Numpy 警告之后,我的代码停止执行。然后我更具体,这解决了问题。
  • 额外的过滤器警告对我提出了一个错误:re.error: nothing to repeat at position 0 with python version 3.7.10 。这是因为message 参数中的正则表达式不是有效的正则表达式,因为* 符号应该跟随一个字符重复。在每个* 之前添加一个.(点)解决了这个问题。
【解决方案3】:

您也可以使用命令行来控制警告:

python -W error::UnicodeWarning your_code.py

来自手册页:

-W 参数
[...] error 引发异常而不是打印警告消息。

这与在代码中添加以下内容具有相同的效果:

import warnings
warnings.filterwarnings('error', category=UnicodeWarning)

正如安迪的回答中已经说过的那样。

【讨论】:

    【解决方案4】:

    调查警告信息最丰富的方法是将其转换为错误 (Exception),以便您可以查看其完整的堆栈跟踪:

    import warnings
    warnings.simplefilter("error")
    

    warnings

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-01
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      相关资源
      最近更新 更多