traceback仅显示多行命令的一行

时间:2016-08-19 15:59:34

标签: python traceback

我在服务器上添加了一个小调试辅助工具。它记录从[Int]$NumFolders = 0 [Int]$NumFiles = 0 $Path = "C:\" $Objects = Get-ChildItem $Path -Recurse $Size = Get-ChildItem $Path -Recurse | Measure-Object -property length -sum $NumFiles = ($Objects | Where { -not $_.PSIsContainer}).Count $NumFolders = ($Objects | Where {$_.PSIsContainer}).Count $Summary = New-Object PSCustomObject -Property @{"Path" = $Path ; "Files" = $NumFiles ; "Folders" = $NumFolders ; "Size in MB" = ([Math]::Round($Size.sum /1MB))} $Summary | Format-list

获得的堆栈跟踪

它包含几个不完整的行:

traceback.format_stack()

这并没有多大帮助。

源代码行360和361:

File "/home/...../base/loop.py", line 361, in run
    self.outputs.fd_list, (), sleep)

如果只有一行可以成为堆栈跟踪的一部分,我会说具有函数名称的行360(此处为rlist, wlist, unused = select.select(self.inputs.fd_list, self.outputs.fd_list, (), sleep) )是正确的,因为堆栈是通过调用函数创建的。

无论如何,我更希望打印整个(逻辑)线。或者至少一些上下文(例如之前的2行)。那可能吗?我的意思是当然只需要付出足够的努力。

尝试添加续行字符select.select,但没有成功。

EPILOGUE : 根据Jean-FrançoisFabre的回答和他的代码,我将使用这个函数:

\

2 个答案:

答案 0 :(得分:1)

“只需​​付出足够的努力”就可以做到这一点。但它很像黑客

检查这个例子:

import traceback,re,os,sys

r = re.compile(r'File\s"(.*)",\sline\s(\d+)')

def print_trace():
    # discard the 2 deepest entries since they're a call to print_trace()
    lines = [str.split(x,"\n")[0] for x in traceback.format_stack()][:-2]

    for l in lines:
        m = r.search(l)
        if m != None:
            sys.stdout.write(l+"\n")
            file = m.group(1)
            line = int(m.group(2))-1
            if os.path.exists(file):
                with open(file,"r") as f:
                    rl = f.readlines()
                    tblines = rl[max(line-2,0):min(line+3,len(rl))]
                    # read 2 lines before and 2 lines after
                    for i,tl in enumerate(tblines):
                        tl = tl.rstrip()

                        if i==2:
                            sys.stdout.write("    "+tl+" <====\n")
                        elif tl:
                            sys.stdout.write("    "+tl+"\n")


def foo():
    print_trace()

foo()

输出:

  File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 63, in <module>
    if __name__ == "__main__":
        main() <====
  File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 60, in main
        t = SimpleServer(ModSlaveService, port = port, auto_register = False)
        t.start() <====
    if __name__ == "__main__":
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 227, in start
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 139, in accept
  File "C:\Users\dartypc\AppData\Roaming\PyScripter\remserver.py", line 14, in _accept_method
    class SimpleServer(Server):
        def _accept_method(self, sock):
            self._serve_client(sock, None) <====
    class ModSlaveService(SlaveService):
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\utils\server.py", line 191, in _serve_client
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 391, in serve_all
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 382, in serve
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 350, in _dispatch
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 298, in _dispatch_request
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 528, in _handle_call
  File "<string>", line 420, in run_nodebug
  File "C:\DATA\jff\data\python\stackoverflow\traceback_test.py", line 31, in <module>
        print_trace()
    foo() <====

编辑:VPfB建议使用extract_stack,这有点不那么“hacky”,不需要解析字符串,只需要获得带有追溯信息的四元组(需要重建文本消息,但这样更好)

import traceback,os,sys


def print_trace():
    # discard the 2 deepest entries since they're a call to print_trace()

    for file,line,w1,w2 in traceback.extract_stack()[:-2]:
        sys.stdout.write('  File "{}", line {}, in {}\n'.format(file,line,w1))

        if os.path.exists(file):
            line -= 1
            with open(file,"r") as f:
                rl = f.readlines()
                tblines = rl[max(line-2,0):min(line+3,len(rl))]
                # read 2 lines before and 2 lines after
                for i,tl in enumerate(tblines):
                    tl = tl.rstrip()

                    if i==2:
                        sys.stdout.write("    "+tl+" <====\n")
                    elif tl:
                        sys.stdout.write("    "+tl+"\n")


def foo():
    print_trace()

foo()

答案 1 :(得分:0)

traceback.format_exception_only函数格式只有一行, SyntaxError 除外,所以......