-
-
Notifications
You must be signed in to change notification settings - Fork 31.2k
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
pdb/bdb changes for PEP 669 #103103
Comments
This should target 3.13. 3.12 beta1 is due May 8, less that 6 weeks and AFAIK 669 is not yet implemented. It will likely need some time before we can code anything using it. Besides which, touching bdb and pdb are not part of 669 and choosing one of the approaches above might need a PEP (or more than one if competing ideas). I believe 3. is not an option. 4. has two versions: About 5 years ago Cheryl Sabella and I added docstrings to bdb and likely edited it doc -- so we could better understand IDLE's bdb subclass, used for IDLE's visual debugger ('vdb'). Though I could be wrong, my memory is that bdb's code was not the best I have seen and might stand a rewrite. If a bdb re-write implemented the same API, then pdb would not need much change to use either old or new. But the API may have been part of what I did not like, and I have no idea at the moment whether it can sensibly remain as is (to make best use of the new 669 mechanism). One of my back burner ideas has been to make vdb usable even if one were not using IDLE. I good time to explore this would be when revising vdb to use bdb2, however it ends up. To me, not having learned to use pdb, pdb looks old-fashioned and hard to use. I am pretty sure that many others in the same position react the same way. |
Yes but also no. We don't have to land the pdb/bdb changes for 3.12, I agree with that. But we need to start implementing them ASAP. It will be a huge missed opportunity if we don't exercise the PEP 669 implementation (which itself is currently being worked on) by implementing a debugger on top of that. That way we have a chance to discover issues early affecting a use case like a new pdb. Like, AsyncIO informed async/await and if it weren't for the built-in framework, I think it's unlikely we'd grow out of Back to the question at hand, it seems to me that:
That leaves us essentially with Terry's "4b", which is to create a new fast debugger based on PEP 669. I think it's the right way forward as there are a few good opportunities here that would be hard to achieve with Since that's a new project under a new module name, it's not a given it would end up in the standard library. And maybe it doesn't have to. We might go with a separate project within the Python organization on GitHub for this, like what MyPy is doing. This would allow us to use PyPI libraries in the implementation for stuff like auto-completion, syntax highlighting, text UIs, and so on. If it works out well, at some point we might bring it into the standard library or bundle it like we do with pip. Definitely not a concern for now. What matters now is to start on the new debugger to test how PEP 669 feels. And a prerequisite of that is getting GH-103083 landed 🤞🏻 |
pdb is a user interfacing layer so I don't see why we can't keep backward compatibility while switching the current bdb out. We can keep all the commands and functions(those are pretty standard for a debugger) so the existing tools relying on it won't be broken (or can be easily adapted). A fancy debugger is great but I believe we have to have a command line working debugger in the standard libraries(battery included right?). The more 3rd-party libs we need (colorma? TUI-related stuff? auto-complete?), the harder it is to make into the standard libraries. There are already fancy debuggers out there like debugpy + IDE(VSCode, PyCharm), and an essential basic debugger should always be present. That's what I was going to discuss in this issue originally. If we want to start a whole new project utilizing the new hooks to build a new debugger, that's totally fine, but what about pdb? It's a thing that users are already familiar with. I guess the question here is - what would be different from the user's view between pdb2 and pdb? Are we going to change the debugger commands? Which commands are we not happy with? Are we going to change its interface? About multi-threading debugging, that's actually one of my next proposals for pdb. I don't think we "automatically" get the feature with PEP 669 and I think we have almost the same capability with the current infrastructure. Of course if we decided to abandon pdb then we only need to worry about PEP 669. There are some issues related, for example, stop-mode vs run-mode(whether all the threads are halted when we are debugging). How can we halt an arbitrary thread. I believe it's doable but it also lacks some essential work there. Therefore I'd suggest to discuss it in a separate issue. |
@gaogaotiantian could you please provide more details about your concerns regarding PEP-669 and multithreading? I have been experimenting with the implementation a little bit, and it appears that multithreading can be achieved out of the box. I have prepared a small demo based on the original example from @markshannon. Feel free to share your opinion and any further ideas. Furthermore, I believe it would be great to provide good demos of how (and why) PEP-669 can be used in the monitoring tools before it is finally accepted and merged. |
@ortem because debugger is more than "triggering a function and do something". Yes with PEP 669 you can trigger a function in all threads, but you can do that in current design as well (with Imagine you are debugging a thread, and a breakpoint of another thread hits - what will happen? Their behavior can not be symmetric because you only have one input channel. Or imaging one of the thread is constantly outputing strings, how could you debug other threads? Your debugger interface would be messed up by the outputs. A real multithreading debugger needs to be able to switch to an arbitrary thread context and execute code/monitor variables in that context, how would a debugger do that? To achieve this, the easiest way is to do "stop-mode" debugging, which means once we hit a breakpoint or a "stoppoint", halt all threads. In this case, we don't need to worry about impacts from all the other threads and we can maybe switch context without hassle. However, I don't believe Python has provided such a mechanism at the moment. The more intuitive and also essential mode is "run-mode", where all the threads are running freely except for the one we debugged. We need a lot of extra care in this mode because of the reasons I mentioned above. This is quite a project. Preferably, we can halt arbitrary thread in the debugger to debug it. All the stuff (which is just the tip of the iceburg) requires extra support from the under layer of Python and a lot of work. I don't believe it can be done "out of the box". |
Indeed, a thread-aware debugger is not a simple thing, but it should be possible with PEP 669. @gaogaotiantian Do you think it would need extra support from the VM, or do you just mean that it cannot be done in pure Python? |
As for the original suggestion of porting pdb to PEP 669: The bdb module's interface depends on Reimplementing pdb on top PEP 669 should be possible, as the interface is higher level (although there is a Personally, I think it might be too late to do either for 3.12, but don't let me stop you trying. |
I did some rethink on this matter, and it might be possible to do multi-thread debugging on pure python level. For stop mode, we can add a mutex for the debugger so only one thread has control to it. Every time we hit a breakpoint or stopped somewhere, we set the global LINE/INSTRUCTION event and in the callback all the threads need to get the lock before continue. This should equivalently halt all threads. We need some well-designed logic to restart the program - so users don't need to do However, I don't see a way to easily let an arbitrary thread run - PEP 669 is interpreter level, so we can't trigger/disable events on a specific event. That might eliminate the possibility of run mode. From my personal perspective, even having only stop-mode debugging support for multi-thread is a huge improvement on current debugger. And I agree, the time frame is too narrow for 3.12, we should shoot for 3.13. We also need time to figure out how we should proceed this (new bdb? whole new debugger?). Do we still support current In the meantime, I'm trying to polish the current |
Worked on a prototype debugger based on PEP 669. I think we can make the pdb interface the same as before if we wanted to. The events states need extra caring. I only implemented |
Some preliminary numbers for the debugger based on PEP 669. I had a basic implementation on breakpoints and tested with it. def f(x):
# Set breakpoint here
x *= 2
return x + 1
def fib(x):
if x < 2:
return 1
return fib(x - 1) + fib(x - 2)
def test():
start_time = time.time()
fib(24)
cost = time.time() - start_time
print(cost)
f(0)
test() We had a time consuming function The With current With VSCode debugger(debugpy), it takes ~65ms with or without the breakpoint. The debugger itself slows down the execution. Overall the results looks promising. |
@fabioz the numbers above might be interesting to you. I expected debugpy's performance to be closer to the baseline, given that PEP 523 is being heavily leveraged. |
I had a very basic prototype for PEP 669 debugger now. I think we need to discuss if this is the right approach before I proceed more. An extra layer(currently named However, for the breakpoint set on files, we still need to fire the The current implementation still have two debugger classes - One interesting thing to notice is that - we have tool id now. Not like we can do The interface between classes are clearer. As of now, the following
which I believe already comprise the most essential part of The code is still far from ready to be officially reviewed, but it's kind of working. I'd love some feedbacks from people (and preferably at least some core devs?) for the matter. The most important ones are:
Performance wise, PEP 669 based debugger is crushing all the debuggers in the market, but it's not like we are trying to sell a product and have to hit the market fast :) |
@gaogaotiantian Thanks for working on this.
The cost of once per code object should be effectively zero, or do you mean once per call to the code object? In which case returning
I'd be inclined to unconditionally use
I'm very happy to hear that. To answer your questions:
I think you are now the expert on this, so it is up to you 🙂
We will have to support
Yes, it seems reasonable to target 3.13 for this. |
It's once per code object. The performance cost is non-observable at this point. I mentioned that because I don't know if there's any magic to just "get the code object".
The issue I had here is - in the test, multiple debuggers are instantiated. Also it's possible in the future for the users to do multiple Another possible solution is for the
Maintenance of |
Having switched to Python for data-driven development from IDL, one thing I really miss about the latter is that the debugger is "always running". That is, to activate debugging in some code, just set a breakpoint. Stepping, continuing, etc. are just special functions. Given how cheap PEP 669 makes few-breakpoint debugging, I wonder if this "always have a debugger running" mode is in the realm of possibility. Looking forward to the increased performance of (i)PDB. |
Feature or enhancement
Adapt pdb/bdb to PEP669
Pitch
After #103082, we will have the chance to build a much faster debugger. For breakpoints, we do not need to trigger trace function all the time and checking for the line number. Other optimizations for commands like
return
are available too.The bad news is - it's almost impossible to do a completely backward compatible transition because the mechanism is quite different.
There are a couple of ways forward:
bdb
as it is and redesignpdb
to use the new base debugger. Encourage users to migrate to the new base debugger while keep supportingbdb
.bdb
, provide two ways to trigger the debugger. User can choose whether to use the oldset_trace
or the new mechanism.bdb
starting 3.12 to use the new mechanism and let users worry about their own tools built upon it.Previous discussion
https://peps.python.org/pep-0669/
Linked PRs
The text was updated successfully, but these errors were encountered: