New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature idea for iPDB: follow context/cause chains #13697
Comments
This is the reason for which I added pypa/pip#9428 back in the day, and wanted to make a command for it in ipdb, but I never figured out a good UX for it. Remember, that apart from Also, remember that you could just do |
Thanks, glad to hear there is some interest in the concept.
Right. But by investigation, I formed the impression that if In any case, it's easy to prefer
Give Do you happen to know if you can substitute the traceback in a running PDB sessions cleanly? |
Yes, that's what I was aiming at. While the API itself seems final, the PEP does not explicitly state that
You can issue There's also an issue in viewing current exception, which has its root cause in Python trying to prevent circular references:
I think it would be convenient to tackle this one too. You already need to find the exception for this to work anyway, so if you give the user an |
Thanks for your thoughts here. I'm thinking mostly about the interface. It's inconvenient to leave an iPDB session to switch to another position along the |
I don't think you can do that in the context of a running trace per-se. Opening a post-mortem doesn't make you loose any variables nor breakpoints either. It just hides some of those things while you inspect the traceback - you can Something tells me this might be a good candidate for implementation inside All that said, in its good old debugger-is-magic fashion, opening a post-mortem inside running session does weird things to the overal behavior:
|
Very interesting; might be a bit hard to keep track of the recursion. I wonder if there is a way to replace the Here's In [5]: def n():
try:
try:
0/0
except Exception as e:
raise Exception("2") from e
except Exception as e2:
raise Exception(f"Foo: {0/0}") |
How about this? Kind-of-sort-of works (complaining about In [10]: n()
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Input In [5], in n()
3 try:
----> 4 0/0
5 except Exception as e:
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Exception Traceback (most recent call last)
Input In [5], in n()
5 except Exception as e:
----> 6 raise Exception("2") from e
7 except Exception as e2:
Exception: 2
During handling of the above exception, another exception occurred:
ZeroDivisionError Traceback (most recent call last)
Input In [10], in <cell line: 1>()
----> 1 n()
Input In [5], in n()
6 raise Exception("2") from e
7 except Exception as e2:
----> 8 raise Exception(f"Foo: {0/0}")
ZeroDivisionError: division by zero
In [11]: %debug
> <ipython-input-5-0a9a7f152f0a>(8)n()
5 except Exception as e:
6 raise Exception("2") from e
7 except Exception as e2:
----> 8 raise Exception(f"Foo: {0/0}")
9
ipdb> import sys; get_ipython().InteractiveTB.pdb.interaction(None, sys.last_value.__context__.__traceback__)
> <ipython-input-5-0a9a7f152f0a>(6)n()
4 0/0
5 except Exception as e:
----> 6 raise Exception("2") from e
7 except Exception as e2:
8 raise Exception(f"Foo: {0/0}")
ipdb> import sys; get_ipython().InteractiveTB.pdb.interaction(None, sys.last_value.__context__.__context__.__traceb
ack__)
> <ipython-input-5-0a9a7f152f0a>(4)n()
2 try:
3 try:
----> 4 0/0
5 except Exception as e:
6 raise Exception("2") from e |
One of the debug issues with code bases that adopt the style of raising (from) in try..except blocks is that the traceback chain becomes disjoint (the classic "The above exception was the direct cause of the following exception").
In practice this means iPDB can only go up and down the call stack of the "last" such exception thrown.
But it's pretty easy to walk along that chain, since exception values include a
__context__
pointer. I wrote a simple magic%chain
to do just this (more info in the doc string): https://gist.github.com/jdtsmith/7e8fb07a63b20681aee74b61897535ddIt simply alters
sys.last_traceback
, which is where iPDB starts. Works well. But I wonder if this wouldn't be better to implement in iPDB itself, e.g. a chain command there. Perhaps even just let the user connect to the next context chain when you run off the end of a traceback, usingup
/down
. This might require restarting PDB under the hood (not sure), but would be a very nice addition.The text was updated successfully, but these errors were encountered: