Python 如何从回溯中提取任何特定的错误消息?

Python 如何从回溯中提取任何特定的错误消息?,python,regex,Python,Regex,我想提取最后一行显示的错误消息。我可以通过拆分来完成它 test_str = """Traceback (most recent call last): File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 59, in testPartExecuto

我想提取最后一行显示的错误消息。我可以通过拆分来完成它

test_str = """Traceback (most recent call last):
    File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 59, in testPartExecutor
        yield
    File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 593, in run
        self._callTestMethod(testMethod)
    File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 550, in _callTestMethod
        method()
    File "/Users/abcd/efgh/ijkl/bin/../tests/abd/dummy/dummy1.py", line 95, in test_abc
        assert False, "FAILING FOR A REASON"
    AssertionError: FAILING FOR A REASON """
    
    last_line = test_str.split("\n")[-1]
    print(last_line.split(":")[-1])
如何使用正则表达式实现同样的效果?
它可以包含任何类型的错误,
AssertionError、AttributeError、TypeError、SyntaxeError
等等。

为什么要使用正则表达式?它在这里没有任何价值

打印(重新拆分(“:”,最后一行,1)[-1])
也许更有用一些

matched=re.match(r'^\s*([^:\s]+):(.*),最后一行)
如果匹配:
错误,消息=matched.groups()
\s
匹配任何空白字符,
*
表示重复零次或多次<代码>[^:\s]匹配任何不是空格或冒号的字符,我们在第一个冒号之前重复这一点

在更高级的术语中,它会在第一段非空格(和非冒号)字符后找到一行包含冒号,并将冒号前的标记和冒号后的所有内容作为两个单独的组进行提取。(第二组也将在冒号后包含任何空格;可以在左括号前添加
\s*
,以修剪任何前导空格。)

但同样,如果你可以不用正则表达式来做这件事,那就去做吧;使用一个只会使这个过程变得更慢、更复杂

如果您想从较长的文本中提取回溯,请尝试

re.match(r'''^Traceback\(最近一次调用last\):
(?:文件“[^\n]+”,第\d+行,位于[^\n]+
[\n]+
)*([^:]+):([^\n]+)'',多行,关于多行)
但这是未经测试的,可能需要一些修改才能处理与您共享的示例不完全相同的示例(特别是,来自不在文件中的代码的错误看起来略有不同;但我也注意到您的示例回溯看起来不像标准回溯,因为间距模式略有不同-此正则表达式以标准格式为目标)

也许会注意到我们如何使用
'''.'''
三重引号字符串将文字换行嵌入正则表达式;我们仍然使用
r
符号将其标记为原始字符串,这样我们就不必将所有反斜杠加倍


re.MULTILINE
标志是一个修饰符,用于更改
^
锚的含义;有了该标志,它在任何行的开头匹配(而没有该标志,它只在输入字符串的开头匹配).

您可以匹配第一行,然后是所有不以回溯或以错误结尾的单词开头的行,以防止过度匹配

^Traceback \(most recent call last\):(?:\r?\n(?![^\S\r\n]*(?:Traceback|\w*Error)\b).*)*\r?\n[^\S\r\n]*(\w*Error:.*)
  • ^
    字符串的开头
  • Traceback\(最近一次呼叫上次\):
    Match
    Traceback(最近一次呼叫上次):
  • (?:
    非捕获组
    • \r?\n
      匹配换行符
    • (?![^\S\r\n]*(?:Traceback |\w*Error)\b)
      声明行不是以
      Traceback
      开头,也不是以
      Error
      结尾的单词
    • *
      匹配整行
  • )*
    关闭非捕获组并重复0多次
  • \r?\n[^\S\r\n]*
    匹配换行符,可选空白字符不带换行符
  • (\w*错误:.*)
    捕获组1,匹配可选单词字符和
    错误:
    ,然后是行的其余部分

例如:

import re

test_str = """Traceback (most recent call last):
    File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 59, in testPartExecutor
        yield
    File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 593, in run
        self._callTestMethod(testMethod)
    File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 550, in _callTestMethod
        method()
    File "/Users/abcd/efgh/ijkl/bin/../tests/abd/dummy/dummy1.py", line 95, in test_abc
        assert False, "FAILING FOR A REASON"
    AssertionError: FAILING FOR A REASON """

pattern = r"^Traceback \(most recent call last\):(?:\r?\n(?![^\S\r\n]*(?:Traceback|\w*Error)\b).*)*\r?\n[^\S\r\n]*(\w*Error:.*)"

match = re.match(pattern, test_str)

if match:
    print(match.group(1))
输出

['AssertionError: FAILING FOR A REASON ']

重新导入
test_str=“”回溯(最近一次呼叫最后一次):
文件“/usr/local/cillar”/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py”,testPartExecutor中第59行
产量
文件“/usr/local/cillar”/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py”,第593行,运行中
self.\u callTestMethod(testMethod)
文件“/usr/local/cillar”/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py”,第550行,in_callTestMethod
方法()
文件“/Users/abcd/efgh/ijkl/bin/。/tests/abd/dummy/dummy1.py”,第95行,在test_abc中
断言False,“因某种原因失败”
AssertionError:由于某种原因失败“”

匹配=重新搜索(r'(?我的意思是“test_str”上的regex不是“last_line”上的regex。最后一行可以包含以下任何一个断言错误、AttributeError、TypeError、SyntaxError等。在应用regex之前,将文本放入行中更有意义。但只需在第二个示例中添加一个
re.MULTILINE
标志,即可将其应用于完整的
test_str
。可能应用于cla确认你的实际需求。