回溯仅显示多行命令的一行
traceback shows only one line of a multiline command
我在我的服务器上添加了一个小调试工具。它记录从 traceback.format_stack()
获得的堆栈跟踪
它包含一些不完整的行,如下所示:
File "/home/...../base/loop.py", line 361, in run
self.outputs.fd_list, (), sleep)
这不是很有帮助。
源代码第 360 行和第 361 行:
rlist, wlist, unused = select.select(self.inputs.fd_list,
self.outputs.fd_list, (), sleep)
如果只有一行可以作为堆栈跟踪的一部分,我会说带有函数名称的第 360 行(此处 select.select
)是正确的,因为堆栈是通过调用函数创建的。
无论如何,我希望打印整行(逻辑)。或者至少是一些上下文(例如之前的 2 行)。那可能吗?我的意思是,当然要付出足够的努力。
尝试添加续行符 \
,但没有成功。
尾声:
根据 Jean-François Fabre 的回答和他的代码,我将使用这个函数:
def print_trace():
for fname, lnum, func, line in traceback.extract_stack()[:-1]:
print('File "{}", line {}, in {}'.format(fname, lnum, func))
try:
with open(fname) as f:
rl = f.readlines()
except OSError:
if line is not None:
print(" " + line + " <===")
continue
first = max(0, lnum-3)
# read 2 lines before and 2 lines after
for i, line in enumerate(rl[first:lnum+2]):
line = line.rstrip()
if i + first + 1 == lnum:
print(" " + line + " <===")
elif line:
print(" " + line)
traceback.format_exception_only
函数只格式化一行,除了SyntaxError,所以...
"just with adequate effort"这个是可以做到的。但它很像黑客
检查这个例子:
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\Whosebug\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()
我在我的服务器上添加了一个小调试工具。它记录从 traceback.format_stack()
它包含一些不完整的行,如下所示:
File "/home/...../base/loop.py", line 361, in run
self.outputs.fd_list, (), sleep)
这不是很有帮助。
源代码第 360 行和第 361 行:
rlist, wlist, unused = select.select(self.inputs.fd_list,
self.outputs.fd_list, (), sleep)
如果只有一行可以作为堆栈跟踪的一部分,我会说带有函数名称的第 360 行(此处 select.select
)是正确的,因为堆栈是通过调用函数创建的。
无论如何,我希望打印整行(逻辑)。或者至少是一些上下文(例如之前的 2 行)。那可能吗?我的意思是,当然要付出足够的努力。
尝试添加续行符 \
,但没有成功。
尾声: 根据 Jean-François Fabre 的回答和他的代码,我将使用这个函数:
def print_trace():
for fname, lnum, func, line in traceback.extract_stack()[:-1]:
print('File "{}", line {}, in {}'.format(fname, lnum, func))
try:
with open(fname) as f:
rl = f.readlines()
except OSError:
if line is not None:
print(" " + line + " <===")
continue
first = max(0, lnum-3)
# read 2 lines before and 2 lines after
for i, line in enumerate(rl[first:lnum+2]):
line = line.rstrip()
if i + first + 1 == lnum:
print(" " + line + " <===")
elif line:
print(" " + line)
traceback.format_exception_only
函数只格式化一行,除了SyntaxError,所以...
"just with adequate effort"这个是可以做到的。但它很像黑客
检查这个例子:
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\Whosebug\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()