ipdb非常棒;哇!问题是,当一个脚本崩溃时,我仍然需要在代码中添加四行,这些行不需要大量的输入,但也不是什么都不需要。例如,假设这是一条坏线:
1 = 2
很自然,我得到了这个:
SyntaxError: can't assign to literal
如果出于任何原因,我想调试这一行,看看这一行之前(或当时堆栈中的其他地方)发生了什么,我通常会如下更改这一行代码:
try:
1 = 2
except:
import traceback;traceback.print_exc()
import ipdb;ipdb.set_trace()
这就完成了任务,但我希望能够在"模式"下运行脚本,在这种模式下,无论何时发生任何事情(假设异常未得到处理),我都会得到相同的结果。
那存在吗?
*******编辑*******
由于@np8的响应,我重新编写了驱动程序脚本,如下所示(其中main
是任意函数):
if __name__ == "__main__":
start = time.time()
args = parser.parse_args()
if args.verbosity > 1:
from ipdb import launch_ipdb_on_exception
with launch_ipdb_on_exception():
print("Launching ipdb on exception!")
main(start, args)
else:
print("NOT launching ipdb on exception!")
main(start, args)
这使我能够从命令行中确定异常是否应该启动ipdb(即,当我正在开发时)(即,脚本在生产中运行时,因此在本例中使用低于2的详细参数)。
您想要的是"后期调试"。获得所需内容的最简单方法是使用运行脚本
ipdb script.py
或
python -m pdb script.py
而不是
python script.py
您可以使用launch_ipdb_on_exception
上下文管理器:
# test.py
from ipdb import launch_ipdb_on_exception
with launch_ipdb_on_exception():
print(x)
运行以上操作将导致启动ipdb:
python .test.py
NameError("name 'x' is not defined",)
> c:tmpdelete_metest.py(4)<module>()
2
3 with launch_ipdb_on_exception():
----> 4 print(x)
ipdb>
pm
是一个函数装饰器,它反映ipdb上下文管理器CCD_ 4。用它来装饰一个函数,如果出现错误,该函数将转到ipdb。名称"pm"来自ipdb.pm()函数,它代表死后,表现相似。
这样,您就可以修饰要使用@pm
调试的顶级函数,并且调用堆栈中该级别或更低级别的任何异常都将触发ipdb。
import ipdb
class Decontext(object):
"""
Makes a context manager also act as decorator
"""
def __init__(self, context_manager):
self._cm = context_manager
def __enter__(self):
return self._cm.__enter__()
def __exit__(self, *args, **kwds):
return self._cm.__exit__(*args, **kwds)
def __call__(self, func):
def wrapper(*args, **kwds):
with self:
return func(*args, **kwds)
return wrapper
pm = Decontext(ipdb.launch_ipdb_on_exception())