检索警告对象的原始包

问题描述 投票:0回答:0

任务

对于暗示使用不同包(例如 pandas、numpy 等)的给定代码块,我需要检索创建的所有警告的列表。

部分解决方案

使用

warnings.catch_warnings(record=True)
我能够“捕获”列表中的所有警告,但是因为执行
warnings.warn
时堆栈级别几乎总是 2,这意味着我只能获得对调用者的引用,而不是调用
warnings.warn
的确切代码段(有了它就很容易提取包名称)

当前解决方案

使用上下文管理器,我可以围绕 warnings.warn 方法构建一个包装器,以便我能够挂钩它并获取该列的原始文件/包。

class MyWarningsCtx:
    def __enter__(self):
        self.old_warn = warnings.warn
        self.warnings = []

        #
        def new_warn(*args, **kwargs):
            frame = inspect.stack()[1]
            p = frame[0].f_code.co_filename
            obj = {"message": args[0], "path": p}
            self.warnings.append(obj)
            self.old_warn(*args, **kwargs)

        warnings.warn = new_warn
        return self.warnings

    def __exit__(self, exc_type, exc_val, exc_tb):
        warnings.warn = self.old_warn

为了测试这一点,我使用以下内容

if __name__ == "__main__":
    df = pd.DataFrame([['1990', 'a', 5, 4, 7, 2], ['1991', 'c', 10, 1, 2, 0], ['1992', 'd', 2, 1, 4, 12], ['1993', 'a', 5, 8, 11, 6]],
                      columns=('Date', 'best', 'a', 'b', 'c', 'd'))

    df.lookup(df.index, df['best'])
    print("\n\n\n\n")
    with MyWarningsCtx() as wrngs:
        df.lookup(df.index, df['best'])
        print("\n\n\n\n")
        print({"parsed_warnings": wrngs})

path_to_current_folder/test_ctx_warnings.py:30: FutureWarning: The 'lookup' method is deprecated and will beremoved in a future version.You can use DataFrame.melt and DataFrame.locas a substitute.
  df.lookup(df.index, df['best'])





path_to_env/site-packages/pandas/core/frame.py:4553: FutureWarning: The 'lookup' method is deprecated and will beremoved in a future version.You can use DataFrame.melt and DataFrame.locas a substitute.
  warnings.warn(msg, FutureWarning, stacklevel=2)





{'parsed_warnings': [{'message': "The 'lookup' method is deprecated and will beremoved in a future version.You can use DataFrame.melt and DataFrame.locas a substitute.", 'path': '/path_to_env/site-packages/pandas/core/frame.py'}]}

现在有几件事我希望你能帮助我:

  1. 是否有其他选项可以实现我正在尝试的目标,而无需“挂钩”并替换 warnings.warn 方法?
  2. 第一次 df.lookup 调用将如预期的那样抛出包含被调用者行的警告(堆栈级别 2)。 df.lookup 的第二次调用,只是因为位于 with 块内,已经抛出警告,但路径不同(正是调用 warnings.warn 的位置 - 这就是我感兴趣的。为什么?我错过了什么?
  3. 当然,打印的 {"parsed_warnings"} 看起来像我想要的,因为我仍在使用
    inspect
    来获取文件。但即使我不使用
    inspect
    也没关系。即使我只做了这样的事情(如下),我仍然会得到
    warnings.warn
    调用的确切行。不知道我错过了什么
def new_warn(*args, **kwargs):
    self.old_warn(*args, **kwargs)
  1. 您对将此类解决方法投入生产有多大信心?
python python-3.9 contextmanager
© www.soinside.com 2019 - 2024. All rights reserved.