__cause__
(由
raise ... from ...
语法定义)呢?
Python 3.7.6 (default, Jan 8 2020, 13:42:34)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.11.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: def foo():
...: bab = 42
...: raise TypeError
...:
In [2]: try:
...: foo()
...: except TypeError as err:
...: barz = 5
...: raise ValueError from err
...:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-2-dd046d7cece0> in <module>
1 try:
----> 2 foo()
3 except TypeError as err:
<ipython-input-1-da9a05838c59> in foo()
2 bab = 42
----> 3 raise TypeError
4
TypeError:
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
<ipython-input-2-dd046d7cece0> in <module>
3 except TypeError as err:
4 barz = 5
----> 5 raise ValueError from err
6
ValueError:
In [3]: %debug
> <ipython-input-2-dd046d7cece0>(5)<module>()
2 foo()
3 except TypeError as err:
4 barz = 5
----> 5 raise ValueError from err
6
ipdb> barz
5
ipdb> bab
*** NameError: name 'bab' is not defined
ipdb> down
*** Newest frame
ipdb> up
*** Oldest frame
有一种方法可以从调试器访问
bab
?
Edit:我意识到验尸后不仅仅是Ipython和IPDB的功能,它实际上是Vanilla PDB的一部分。以上也可以通过将代码放入脚本
testerr.py
并运行python -m pdb testerr.py
并运行
continue
来复制。错误后,它说
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
在同一地点进行调试器。
您可以使用
try:
foo()
except TypeError as err:
barz = 5
raise ValueError().with_traceback(err.__traceback__) from err
注意,我已经更新了代码以提出异常实例而不是异常类别。
iPython中的完整代码段:
In [1]: def foo():
...: bab = 42
...: raise TypeError()
...:
In [2]: try:
...: foo()
...: except TypeError as err:
...: barz = 5
...: raise ValueError().with_traceback(err.__traceback__) from err
...:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-2-a5a6d81e4c1a> in <module>
1 try:
----> 2 foo()
3 except TypeError as err:
<ipython-input-1-ca1efd1bee60> in foo()
2 bab = 42
----> 3 raise TypeError()
4
TypeError:
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
<ipython-input-2-a5a6d81e4c1a> in <module>
3 except TypeError as err:
4 barz = 5
----> 5 raise ValueError().with_traceback(err.__traceback__) from err
6
<ipython-input-2-a5a6d81e4c1a> in <module>
1 try:
----> 2 foo()
3 except TypeError as err:
4 barz = 5
5 raise ValueError().with_traceback(err.__traceback__) from err
<ipython-input-1-ca1efd1bee60> in foo()
1 def foo():
2 bab = 42
----> 3 raise TypeError()
4
ValueError:
In [3]: %debug
> <ipython-input-1-ca1efd1bee60>(3)foo()
1 def foo():
2 bab = 42
----> 3 raise TypeError()
4
ipdb> bab
42
ipdb> u
> <ipython-input-2-a5a6d81e4c1a>(2)<module>()
1 try:
----> 2 foo()
3 except TypeError as err:
4 barz = 5
5 raise ValueError().with_traceback(err.__traceback__) from err
ipdb> u
> <ipython-input-2-a5a6d81e4c1a>(5)<module>()
2 foo()
3 except TypeError as err:
4 barz = 5
----> 5 raise ValueError().with_traceback(err.__traceback__) from err
6
ipdb> barz
5
Edit-一种替代的下等方法 addressing @user2357112SupportsMonica的
firstcomment,如果您希望避免在日志中避免原始异常的追踪的多个转储,则可以
raise from None
try:
foo()
except TypeError as err:
barz = 5
raise ValueError().with_traceback(err.__traceback__) from None
在
Ipython中的代码片段:
In [4]: try:
...: foo()
...: except TypeError as err:
...: barz = 5
...: raise ValueError().with_traceback(err.__traceback__) from None
...:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-6-b090fb9c510e> in <module>
3 except TypeError as err:
4 barz = 5
----> 5 raise ValueError().with_traceback(err.__traceback__) from None
6
<ipython-input-6-b090fb9c510e> in <module>
1 try:
----> 2 foo()
3 except TypeError as err:
4 barz = 5
5 raise ValueError().with_traceback(err.__traceback__) from None
<ipython-input-2-ca1efd1bee60> in foo()
1 def foo():
2 bab = 42
----> 3 raise TypeError()
4
ValueError:
In [5]: %debug
> <ipython-input-2-ca1efd1bee60>(3)foo()
1 def foo():
2 bab = 42
----> 3 raise TypeError()
4
ipdb> bab
42
ipdb> u
> <ipython-input-6-b090fb9c510e>(2)<module>()
1 try:
----> 2 foo()
3 except TypeError as err:
4 barz = 5
5 raise ValueError().with_traceback(err.__traceback__) from None
ipdb> u
> <ipython-input-6-b090fb9c510e>(5)<module>()
3 except TypeError as err:
4 barz = 5
----> 5 raise ValueError().with_traceback(err.__traceback__) from None
6
ipdb> barz
5
需要priansingfrom None
,因为否则将进行链接implicry,将原始异常作为新的例外属性。请注意,这与明确完成链接时设置的__context__
__cause__
yoel答案有效,应该是您的首选过程,但是如果跟踪更难调试,则可以使用
In [6]: try:
...: foo()
...: except TypeError as err:
...: barz = 5
...: raise ValueError().with_traceback(err.__traceback__)
...:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-ee78991171cb> in <module>
1 try:
----> 2 foo()
3 except TypeError as err:
<ipython-input-2-ca1efd1bee60> in foo()
2 bab = 42
----> 3 raise TypeError()
4
TypeError:
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
<ipython-input-5-ee78991171cb> in <module>
3 except TypeError as err:
4 barz = 5
----> 5 raise ValueError().with_traceback(err.__traceback__)
6
<ipython-input-5-ee78991171cb> in <module>
1 try:
----> 2 foo()
3 except TypeError as err:
4 barz = 5
5 raise ValueError().with_traceback(err.__traceback__)
<ipython-input-2-ca1efd1bee60> in foo()
1 def foo():
2 bab = 42
----> 3 raise TypeError()
4
ValueError:
模块。
跟踪模块将打印出执行的每个指令,按行线。不过,有一个渔获。标准库和软件包调用也将被追踪,这可能意味着该跟踪将充斥着没有意义的代码。要避免这种行为,您可以通过python库和站点包装文件夹的位置传递
trace
参数。
run--ignore-dir
要找到网站包的位置,然后以以下参数调用跟踪:python -m site
用所有文件夹重新置换
python -m trace --trace --ignore-dir=/usr/lib/python3.8:/usr/local/lib/python3.8/dist-packages main.py args
,并使用脚本位置和参数。
如果要运行某个功能,您也可以直接在代码中使用跟踪模块,请参阅此示例从
Https://docs.python.org/3.0/library/trace.html:
中提取的示例。
ignore-dir
i我还找到了一种方法来执行此操作,而无需修改基础源代码 - 简单地在Mortem Debugger中运行命令。 i从this Answer那里看到了您可以直接从追溯实例获得当地人。
main.py args
由于后者使用后者,您可以简单地沿着一系列例外移动,然后通过覆盖所需的级别进行调试。 从
import sys
import trace
# create a Trace object, telling it what to ignore, and whether to
# do tracing or line-counting or both.
tracer = trace.Trace(
ignoredirs=[sys.prefix, sys.exec_prefix],
trace=0,
count=1)
# run the new command using the given tracer
tracer.run('main()')
# make a report, placing output in /tmp
r = tracer.results()
r.write_results(show_missing=True, coverdir="/tmp")
开始,将(Pdb) ll
1 -> def foo():
2 bab = 42
3 raise TypeError
4
5 try:
6 foo()
7 except TypeError as err:
8 barz = 5
9 >> raise ValueError from err
10
(Pdb) err # not sure why err is not defined
*** NameError: name 'err' is not defined
(Pdb) import sys
(Pdb) sys.exc_info()
(<class 'AttributeError'>, AttributeError("'Pdb' object has no attribute 'do_sys'"), <traceback object at 0x107cb5be0>)
(Pdb) err = sys.exc_info()[1].__context__
(Pdb) err # here we go
ValueError()
(Pdb) err.__cause__
TypeError()
(Pdb) err.__traceback__.tb_next.tb_next.tb_next.tb_next.tb_frame.f_locals['barz']
5
(Pdb) err.__cause__.__traceback__.tb_next.tb_frame.f_locals['bab']
42
链沿所需的水平(sys.last_value.__traceback__ is sys.last_traceback
)走,然后设置
ipdb
。i写了一个小小的ipython魔术,
new
sys.last_traceback = new.__traceback__
启用堆栈快照后,更容易,更方便地确定问题,同时知道%debug
和~/.ipython/profile_default/startup
的值::
%chain -h
也可以手动输出外观:
pip install stack-snapshot
仅通过修改
import stack_snapshot; stack_snapshot.init()
方法,例如import stack_snapshot
def inner(x, y):
return x / y
stack_snapshot.init()
x = 1; y = 0
print(inner(x, y))
,
或将函数调用重定向到异常类,例如Traceback (most recent call last):
File "PyStackSnapshot\test.py", line 9, in <module>
print(inner(x,y))
File "PyStackSnapshot\test.py", line 4, in inner
if y == 0: raise ZeroDivisionError
ZeroDivisionError
工具中,包括chatgpt,使它们生成更精确的代码。
在这里可以看到更多详细的用法及其工作方式:Pystacksnapshot·github,我是x
库的开发人员。