Re: [Python-Dev] PEP 553
Hope you don't mind me CC'ing python-dev. On Sun, Oct 1, 2017 at 9:38 AM, Barry Warsaw <barry@python.org> wrote:
You seem to be in PEP review mode :)
What do you think about 553? Still want to wait, or do you think it’s missing anything? So far, all the feedback has been positive, and I think we can basically just close the open issues and both the PEP and implementation are ready to go.
Happy to do more work on it if you feel it’s necessary. -B
I'm basically in agreement. Some quick notes: - There's a comma instead of a period at the end of the 4th bullet in the Rationale: "Breaking the idiom up into two lines further complicates the use of the debugger," . Also I don't understand how this complicates use (even though I also always type it as one line). And the lint warning is actually useful when you accidentally leave this in code you send to CI (assuming that runs a linter, as it should). TBH the biggest argument (to me) is that I simply don't know *how* I would enter some IDE's debugger programmatically. I think it should also be pointed out that even if an IDE has a way to specify conditional breakpoints, the UI may be such that it's easier to just add the check to the code -- and then the breakpoint() option is much more attractive than having to look up how it's done in your particular IDE (especially since this is not all that common). - There's no rationale for the *args, **kwds part of the breakpoint() signature. (I vaguely recall someone on the mailing list asking for it but it seemed far-fetched at best.) - The explanation of the relationship between sys.breakpoint() and sys.__breakpointhook__ was unclear to me -- I had to go to the docs for __displayhook__ ( https://docs.python.org/3/library/sys.html#sys.__displayhook__) to understand that sys.__breakpointhook__ is simply initialized to the same function as sys.breakpointhook, and the idea is that if you screw up you can restore sys.breakpointhook from the other rather than having to restart your process. Is that in fact it? The text "``sys.__breakpointhook__`` then stashes the default value of ``sys.breakpointhook()`` to make it easy to reset" seems to imply some action that would happen... when? how? - Some pseudo-code would be nice. It seems that it's like this: # in builtins def breakpoint(*args, **kwds): import sys return sys.breakpointhook(*args, **kwds) # in sys def breakpointhook(*args, **kwds): import os hook = os.getenv('PYTHONBREAKPOINT') if hook == '0': return None if not hook: import pdb return pdb.set_trace(*args, **kwds) if '.' not in hook: import builtins mod = builtins funcname = hook else: modname, funcname = hook.rsplit('.', 1) __import__(modname) import sys mod = sys.modules[modname] func = getattr(mod, funcname) return func(*args, **kwds) __breakpointhook__ = breakpointhook Except that the error handling should be a bit better. (In particular the PEP specifies a try/except around most of the code in sys.breakpointhook() that issues a RuntimeWarning and returns None.) - Not sure what the PEP's language around evaluation of PYTHONBREAKPOINT means for the above pseudo code. I *think* the PEP author's opinion is that the above pseudo-code is fine. Since programs can mutate their own environment, I think something like `os.environ['PYTHONBREAKPOINT'] = 'foo.bar.baz'; breakpoint()` should result in foo.bar.baz() being imported and called, right? - I'm not quite sure what sort of fast-tracking for PYTHONBREAKPOINT=0 you had in mind beyond putting it first in the code above. - Did you get confirmation from other debuggers? E.g. does it work for IDLE, Wing IDE, PyCharm, and VS 2015? - I'm not sure what the point would be of making a call to breakpoint() a special opcode (it seems a lot of work for something of this nature). ISTM that if some IDE modifies bytecode it can do whatever it well please without a PEP. - I don't see the point of calling `pdb.pm()` at breakpoint time. But it could be done using the PEP with `import pdb; sys.breakpointhook = pdb.pm` right? So this hardly deserves an open issue. - I haven't read the actual implementation in the PR. A PEP should not depend on the actual proposed implementation for disambiguation of its specification (hence my proposal to add pseudo-code to the PEP). That's what I have! -- --Guido van Rossum (python.org/~guido <http://python.org/%7Eguido>)
On 10/2/2017 12:44 AM, Guido van Rossum wrote:
- There's no rationale for the *args, **kwds part of the breakpoint() signature. (I vaguely recall someone on the mailing list asking for it but it seemed far-fetched at best.)
If IDLE's event-driven GUI debugger were rewritten to run in the user process, people wanting to debug a tkinter program should be able to pass in their root, with its mainloop, rather than having the debugger create its own, as it normally would. Something else could come up.
- The explanation of the relationship between sys.breakpoint() and sys.__breakpointhook__ was unclear to me -- I had to go to the docs for __displayhook__ (https://docs.python.org/3/library/sys.html#sys.__displayhook__) to understand that sys.__breakpointhook__ is simply initialized to the same function as sys.breakpointhook, and the idea is that if you screw up you can restore sys.breakpointhook from the other rather than having to restart your process. Is that in fact it? The text "``sys.__breakpointhook__`` then stashes the default value of ``sys.breakpointhook()`` to make it easy to reset" seems to imply some action that would happen... when? how?
- Some pseudo-code would be nice. It seems that it's like this:
This will be helpful to anyone implementing their own breakpointhook.
# in builtins def breakpoint(*args, **kwds): import sys return sys.breakpointhook(*args, **kwds)
# in sys def breakpointhook(*args, **kwds): import os hook = os.getenv('PYTHONBREAKPOINT') if hook == '0': return None if not hook: import pdb return pdb.set_trace(*args, **kwds)
if '.' not in hook: import builtins mod = builtins funcname = hook else: modname, funcname = hook.rsplit('.', 1) __import__(modname) import sys mod = sys.modules[modname] func = getattr(mod, funcname) return func(*args, **kwds)
__breakpointhook__ = breakpointhook
Except that the error handling should be a bit better. (In particular the PEP specifies a try/except around most of the code in sys.breakpointhook() that issues a RuntimeWarning and returns None.)
- Not sure what the PEP's language around evaluation of PYTHONBREAKPOINT means for the above pseudo code. I *think* the PEP author's opinion is that the above pseudo-code is fine. Since programs can mutate their own environment, I think something like `os.environ['PYTHONBREAKPOINT'] = 'foo.bar.baz'; breakpoint()` should result in foo.bar.baz() being imported and called, right?
- I'm not quite sure what sort of fast-tracking for PYTHONBREAKPOINT=0 you had in mind beyond putting it first in the code above.
- Did you get confirmation from other debuggers? E.g. does it work for IDLE, Wing IDE, PyCharm, and VS 2015?
- I'm not sure what the point would be of making a call to breakpoint() a special opcode (it seems a lot of work for something of this nature). ISTM that if some IDE modifies bytecode it can do whatever it well please without a PEP.
- I don't see the point of calling `pdb.pm <http://pdb.pm>()` at breakpoint time. But it could be done using the PEP with `import pdb; sys.breakpointhook = pdb.pm <http://pdb.pm>` right? So this hardly deserves an open issue.
- I haven't read the actual implementation in the PR. A PEP should not depend on the actual proposed implementation for disambiguation of its specification (hence my proposal to add pseudo-code to the PEP).
-- Terry Jan Reedy
On Sun, Oct 1, 2017 at 11:15 PM, Terry Reedy <tjreedy@udel.edu> wrote:
On 10/2/2017 12:44 AM, Guido van Rossum wrote:
- There's no rationale for the *args, **kwds part of the breakpoint()
signature. (I vaguely recall someone on the mailing list asking for it but it seemed far-fetched at best.)
If IDLE's event-driven GUI debugger were rewritten to run in the user process, people wanting to debug a tkinter program should be able to pass in their root, with its mainloop, rather than having the debugger create its own, as it normally would. Something else could come up.
But if they care so much, they could also use a small wrapper as the sys.breakpointhook that retrieves the root and calls the IDLE debugger with that. Why is adding the root to the breakpoint() call better than that? To me, the main attraction for breakpoint is that there's something I can type quickly and insert at any point in the code. During a debugging session I may try setting it in many different places. If I have to also pass the root each time I type "breakpoint()" that's just an unnecessary detail compared to having it done automatically by the hook. -- --Guido van Rossum (python.org/~guido)
Thanks for the review Guido! The PEP and implementation have been updated to address your comments, but let me briefly respond here.
On Oct 2, 2017, at 00:44, Guido van Rossum <guido@python.org> wrote:
- There's a comma instead of a period at the end of the 4th bullet in the Rationale: "Breaking the idiom up into two lines further complicates the use of the debugger,” .
Thanks, fixed.
Also I don't understand how this complicates use
I’ve addressed that with some additional wording in the PEP. Basically, it’s my contention that splitting it up on two lines introduces more opportunity for mistakes.
TBH the biggest argument (to me) is that I simply don't know *how* I would enter some IDE's debugger programmatically. I think it should also be pointed out that even if an IDE has a way to specify conditional breakpoints, the UI may be such that it's easier to just add the check to the code -- and then the breakpoint() option is much more attractive than having to look up how it's done in your particular IDE (especially since this is not all that common).
This is a really excellent point! I’ve reworked that section of the PEP to make this clear.
- There's no rationale for the *args, **kwds part of the breakpoint() signature. (I vaguely recall someone on the mailing list asking for it but it seemed far-fetched at best.)
I’ve added some rationale. The idea comes from optional `header` argument to IPython’s programmatic debugger API. I liked that enough to add it to pdb.set_trace() for 3.7. IPython accepts other optional arguments, so I think we do want to allow those to be passed through the call chain. I expect any debugger’s advertised entry point to make these optional, so `breakpoint()` will always just work.
- The explanation of the relationship between sys.breakpoint() and sys.__breakpointhook__ was unclear to me
I think you understand it correctly, and I’ve hopefully clarified that in the PEP now, so you wouldn’t have to read the __displayhook__ (or __excepthook__) docs to understand how it works.
- Some pseudo-code would be nice.
Great idea; added that to the PEP (pretty close to what you have, but with the warnings handling, etc.)
I think something like `os.environ['PYTHONBREAKPOINT'] = 'foo.bar.baz'; breakpoint()` should result in foo.bar.baz() being imported and called, right?
Correct. Clarified in the PEP now.
- I'm not quite sure what sort of fast-tracking for PYTHONBREAKPOINT=0 you had in mind beyond putting it first in the code above.
That’s pretty close to it. Clarified.
- Did you get confirmation from other debuggers? E.g. does it work for IDLE, Wing IDE, PyCharm, and VS 2015?
From some of them, yes. Terry confirmed for IDLE, and I posted a statement in favor of the PEP from the PyCharm folks. I’m pretty sure Steve confirmed that this would be useful for VS, and I haven’t heard from the Wing folks.
- I'm not sure what the point would be of making a call to breakpoint() a special opcode (it seems a lot of work for something of this nature). ISTM that if some IDE modifies bytecode it can do whatever it well please without a PEP.
I’m strongly against including anything related to a new bytecode to PEP 553; they’re just IMHO orthogonal issues, and I’ve removed this as an open issue for 553. I understand why some debugger developers want it though. There was a talk at Pycon 2017 about what PyCharm does. They have to rewrite the bytecode to insert a call to a “trampoline function” which in many ways is the equivalent of breakpoint() and sys.breakpointhook(). I.e. it’s a small function that sets up and calls a more complicated function to do the actual debugging. IIRC, they open up space for 4 bytecodes, with all the fixups that implies. The idea was that there could be a single bytecode that essentially calls builtin breakpoint(). Steve indicated that this might also be useful for VS. There’s a fair bit that would have to be fleshed out to make this idea real, but as I say, I think it shouldn’t have anything to do with PEP 553, except that it could probably build on the APIs we’re adding here.
- I don't see the point of calling `pdb.pm()` at breakpoint time. But it could be done using the PEP with `import pdb; sys.breakpointhook = pdb.pm` right? So this hardly deserves an open issue.
Correct, and I’ve removed this open issue.
- I haven't read the actual implementation in the PR. A PEP should not depend on the actual proposed implementation for disambiguation of its specification (hence my proposal to add pseudo-code to the PEP).
That's what I have!
Cool, that’s very helpful, thanks! -Barry
On 10/2/2017 10:45 AM, Guido van Rossum wrote:
On Sun, Oct 1, 2017 at 11:15 PM, Terry Reedy <tjreedy@udel.edu <mailto:tjreedy@udel.edu>> wrote:
On 10/2/2017 12:44 AM, Guido van Rossum wrote:
- There's no rationale for the *args, **kwds part of the breakpoint() signature. (I vaguely recall someone on the mailing list asking for it but it seemed far-fetched at best.)
If IDLE's event-driven GUI debugger were rewritten to run in the user process, people wanting to debug a tkinter program should be able to pass in their root, with its mainloop, rather than having the debugger create its own, as it normally would. Something else could come up.
But if they care so much, they could also use a small wrapper as the sys.breakpointhook that retrieves the root and calls the IDLE debugger with that.
'They' include beginners that need the simplicity of breakpoint() the most.
Why is adding the root to the breakpoint() call better than that? To me, the main attraction for breakpoint is that there's something I can type quickly and insert at any point in the code.
I agree.
During a debugging session I may try setting it in many different places. If I have to also pass the root each time I type "breakpoint()" that's just an unnecessary detail compared to having it done automatically by the hook.
Even though pdb.set_trace re-initializes each call, idb.whatever should *not*. So it should set something that can be queried. My idea was that a person should pass root only on the first call. But that founders on the fact that 'first call' may not be deterministic. if cond: breakpoint() <stuff> <more stuff> breakpoint() Besides which, someone might insert breakpoint() before creating a root. So I will try instead initializing with iroot = tk._default_root if tk._default_root else tk.Tk() and stick with iroot.update() and avoid i.mainloop() A revised tk-based debugger, closer to pdb than it is now, will require some experimentation. I would like to be able to use it to debug IDLE run from a command line, and that will be a fairly severe test of compatibility with a tkinter application. You could approve breakpoint() without args now and add them if and when there were more convincing need. -- Terry Jan Reedy
On Mon, Oct 2, 2017 at 11:02 AM, Barry Warsaw <barry@python.org> wrote:
Thanks for the review Guido! The PEP and implementation have been updated to address your comments, but let me briefly respond here.
On Oct 2, 2017, at 00:44, Guido van Rossum <guido@python.org> wrote:
- There's a comma instead of a period at the end of the 4th bullet in the Rationale: "Breaking the idiom up into two lines further complicates the use of the debugger,” .
Thanks, fixed.
Also I don't understand how this complicates use
I’ve addressed that with some additional wording in the PEP. Basically, it’s my contention that splitting it up on two lines introduces more opportunity for mistakes.
TBH the biggest argument (to me) is that I simply don't know *how* I would enter some IDE's debugger programmatically. I think it should also be pointed out that even if an IDE has a way to specify conditional breakpoints, the UI may be such that it's easier to just add the check to the code -- and then the breakpoint() option is much more attractive than having to look up how it's done in your particular IDE (especially since this is not all that common).
This is a really excellent point! I’ve reworked that section of the PEP to make this clear.
- There's no rationale for the *args, **kwds part of the breakpoint() signature. (I vaguely recall someone on the mailing list asking for it but it seemed far-fetched at best.)
I’ve added some rationale. The idea comes from optional `header` argument to IPython’s programmatic debugger API. I liked that enough to add it to pdb.set_trace() for 3.7. IPython accepts other optional arguments, so I think we do want to allow those to be passed through the call chain. I expect any debugger’s advertised entry point to make these optional, so `breakpoint()` will always just work.
- The explanation of the relationship between sys.breakpoint() and sys.__breakpointhook__ was unclear to me
I think you understand it correctly, and I’ve hopefully clarified that in the PEP now, so you wouldn’t have to read the __displayhook__ (or __excepthook__) docs to understand how it works.
- Some pseudo-code would be nice.
Great idea; added that to the PEP (pretty close to what you have, but with the warnings handling, etc.)
I think something like `os.environ['PYTHONBREAKPOINT'] = 'foo.bar.baz'; breakpoint()` should result in foo.bar.baz() being imported and called, right?
Correct. Clarified in the PEP now.
- I'm not quite sure what sort of fast-tracking for PYTHONBREAKPOINT=0 you had in mind beyond putting it first in the code above.
That’s pretty close to it. Clarified.
- Did you get confirmation from other debuggers? E.g. does it work for IDLE, Wing IDE, PyCharm, and VS 2015?
From some of them, yes. Terry confirmed for IDLE, and I posted a statement in favor of the PEP from the PyCharm folks. I’m pretty sure Steve confirmed that this would be useful for VS, and I haven’t heard from the Wing folks.
- I'm not sure what the point would be of making a call to breakpoint() a special opcode (it seems a lot of work for something of this nature). ISTM that if some IDE modifies bytecode it can do whatever it well please without a PEP.
I’m strongly against including anything related to a new bytecode to PEP 553; they’re just IMHO orthogonal issues, and I’ve removed this as an open issue for 553.
I understand why some debugger developers want it though. There was a talk at Pycon 2017 about what PyCharm does. They have to rewrite the bytecode to insert a call to a “trampoline function” which in many ways is the equivalent of breakpoint() and sys.breakpointhook(). I.e. it’s a small function that sets up and calls a more complicated function to do the actual debugging. IIRC, they open up space for 4 bytecodes, with all the fixups that implies. The idea was that there could be a single bytecode that essentially calls builtin breakpoint(). Steve indicated that this might also be useful for VS.
There’s a fair bit that would have to be fleshed out to make this idea real, but as I say, I think it shouldn’t have anything to do with PEP 553, except that it could probably build on the APIs we’re adding here.
- I don't see the point of calling `pdb.pm()` at breakpoint time. But it could be done using the PEP with `import pdb; sys.breakpointhook = pdb.pm` right? So this hardly deserves an open issue.
Correct, and I’ve removed this open issue.
- I haven't read the actual implementation in the PR. A PEP should not depend on the actual proposed implementation for disambiguation of its specification (hence my proposal to add pseudo-code to the PEP).
That's what I have!
Cool, that’s very helpful, thanks!
I've seen your updates and it is now acceptable, except for *one* nit: in builtins.breakpoint() the pseudo code raises RuntimeError if sys.breakpointhook is missing or None. OTOH sys.breakpointhook() just issues a RuntimeWarning when something's wrong with the hook. Maybe builtins.breakpoint() should also just warn if it can't find the hook? Setting `sys.breakpointhook = None` might be the simplest way to programmatically disable breakpoints. Why not allow it? To Terry: Barry has given another excellent argument for passing through *args, **kwds so I remove my objection to it, regardless of what I think of your argument about the IDLE debugger and root windows. (It's been too long since I used Tkinter, so I don't trust my intuition there much anyways.) -- --Guido van Rossum (python.org/~guido)
On Oct 2, 2017, at 17:36, Guido van Rossum <guido@python.org> wrote:
I've seen your updates and it is now acceptable, except for *one* nit: in builtins.breakpoint() the pseudo code raises RuntimeError if sys.breakpointhook is missing or None. OTOH sys.breakpointhook() just issues a RuntimeWarning when something's wrong with the hook. Maybe builtins.breakpoint() should also just warn if it can't find the hook? Setting `sys.breakpointhook = None` might be the simplest way to programmatically disable breakpoints. Why not allow it?
Oh, actually the pseudocode doesn’t match the C implementation exactly in this regard. Currently the C implementation is more like: def breakpoint(*args, **kws): import sys missing = object() hook = getattr(sys, 'breakpointhook', missing) if hook is missing: raise RuntimeError('lost sys.breakpointhook') return hook(*args, **kws) The intent being, much like the other sys-hooks, that if PySys_GetObject("breakpointhook”) returns NULL, Something Bad Happened, so we have to set an error string and bail. (PySys_GetObject() does not set an exception.) E.g.
def foo(): ... print('yes') ... breakpoint() ... print('no') ... del sys.breakpointhook foo() yes Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in foo RuntimeError: lost sys.breakpointhook
Setting `sys.breakpoint = None` could be an interesting use case, but that’s not currently special in any way:
sys.breakpointhook = None foo() yes Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in foo TypeError: 'NoneType' object is not callable
I’m open to special-casing this if you think it’s useful. (I’ll update the pseudocode in the PEP.) Cheers, -Barry
On Mon, Oct 2, 2017 at 3:03 PM, Barry Warsaw <barry@python.org> wrote:
On Oct 2, 2017, at 17:36, Guido van Rossum <guido@python.org> wrote:
I've seen your updates and it is now acceptable, except for *one* nit: in builtins.breakpoint() the pseudo code raises RuntimeError if sys.breakpointhook is missing or None. OTOH sys.breakpointhook() just issues a RuntimeWarning when something's wrong with the hook. Maybe builtins.breakpoint() should also just warn if it can't find the hook? Setting `sys.breakpointhook = None` might be the simplest way to programmatically disable breakpoints. Why not allow it?
Oh, actually the pseudocode doesn’t match the C implementation exactly in this regard. Currently the C implementation is more like:
def breakpoint(*args, **kws): import sys missing = object() hook = getattr(sys, 'breakpointhook', missing) if hook is missing: raise RuntimeError('lost sys.breakpointhook') return hook(*args, **kws)
The intent being, much like the other sys-hooks, that if PySys_GetObject("breakpointhook”) returns NULL, Something Bad Happened, so we have to set an error string and bail. (PySys_GetObject() does not set an exception.)
E.g.
def foo(): ... print('yes') ... breakpoint() ... print('no') ... del sys.breakpointhook foo() yes Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in foo RuntimeError: lost sys.breakpointhook
Setting `sys.breakpoint = None` could be an interesting use case, but that’s not currently special in any way:
sys.breakpointhook = None foo() yes Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in foo TypeError: 'NoneType' object is not callable
I’m open to special-casing this if you think it’s useful.
(I’ll update the pseudocode in the PEP.)
OK. That then concludes the review of your PEP. It is now accepted! Congrats. I am looking forward to using the backport. :-) -- --Guido van Rossum (python.org/~guido)
On Oct 2, 2017, at 18:43, Guido van Rossum <guido@python.org> wrote:
OK. That then concludes the review of your PEP. It is now accepted! Congrats. I am looking forward to using the backport. :-)
Yay, thanks! We’ll see if I can sneak that backport past Ned. :) -Barry
Barry suggested I bring this up here. It seems the right time to at least discuss this: RE: PEP 553 enabling / disabling breakpoints --- I've recently started using a simple conditional breakpoint in ipython, and wonder if - in addition to Nick Coghlan's request for the env 'PYTHONBREAKPOINT' (boolean?), it would make sense (I _think_ so) to add a condition parameter to the breakpoint() call. This does raise several questions, but it seems that it could make for a simple unified way to conditionally call an arbitrary debugger. What I found useful (in the contecxt of ipython - but general enough) you can see in this gist: https://gist.github.com/yarko/bdaa9d3178a6db03e160fdbabb3a9885 If PEP 553's breakpoint() were to follow this sort of interface (with "condition"), it raises a couple of questions: - how would a missing (default) parameter be done? - how would parameters to be passed to the debugger "of record" be passed in (named tuple? - sort of ugly) - would PYTHONBREAKPOINT be a global switch (I think yes), vs a `condition` default. I have no dog in the fight, but to raise the possibility (?) of having PEP 553 implement simple conditional breakpoint processing. Any / all comments much appreciated. Regards, Yarko On Mon, Oct 2, 2017 at 7:06 PM, Barry Warsaw <barry@python.org> wrote:
On Oct 2, 2017, at 18:43, Guido van Rossum <guido@python.org> wrote:
OK. That then concludes the review of your PEP. It is now accepted!
Congrats. I am looking forward to using the backport. :-)
Yay, thanks! We’ll see if I can sneak that backport past Ned. :)
-Barry
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ yarkot1%40gmail.com
On 10/4/2017 5:22 PM, Yarko Tymciurak wrote:
Barry suggested I bring this up here.
It seems the right time to at least discuss this:
RE: PEP 553 enabling / disabling breakpoints ---
I've recently started using a simple conditional breakpoint in ipython, and wonder if - in addition to Nick Coghlan's request for the env 'PYTHONBREAKPOINT' (boolean?), it would make sense (I _think_ so) to add a condition parameter to the breakpoint() call. This does raise several questions, but it seems that it could make for a simple unified way to conditionally call an arbitrary debugger. What I found useful (in the contecxt of ipython - but general enough) you can see in this gist: https://gist.github.com/yarko/bdaa9d3178a6db03e160fdbabb3a9885
If PEP 553's breakpoint() were to follow this sort of interface (with "condition"), it raises a couple of questions: - how would a missing (default) parameter be done? - how would parameters to be passed to the debugger "of record" be passed in (named tuple? - sort of ugly) - would PYTHONBREAKPOINT be a global switch (I think yes), vs a `condition` default.
I have no dog in the fight, but to raise the possibility (?) of having PEP 553 implement simple conditional breakpoint processing.
Any / all comments much appreciated.
breakpoint() already accepts arguments. Therefore no change to the PEP is needed to implement your suggestion. What you are suggesting is simply a convention among debuggers to handle a parameter named "condition" in a particular manner. It seems to me that if condition: breakpoint() would be faster and clearer, but there is nothing to prevent a debugger from implementing your suggestion if it seems useful to the developers of the debugger. If it is useful enough to enough people, the users will clamor for other debuggers to implement it also.
On Oct 4, 2017, at 20:22, Yarko Tymciurak <yarkot1@gmail.com> wrote:
I've recently started using a simple conditional breakpoint in ipython, and wonder if - in addition to Nick Coghlan's request for the env 'PYTHONBREAKPOINT' (boolean?), it would make sense (I _think_ so) to add a condition parameter to the breakpoint() call. This does raise several questions, but it seems that it could make for a simple unified way to conditionally call an arbitrary debugger. What I found useful (in the contecxt of ipython - but general enough) you can see in this gist: https://gist.github.com/yarko/bdaa9d3178a6db03e160fdbabb3a9885
If PEP 553's breakpoint() were to follow this sort of interface (with "condition"), it raises a couple of questions: - how would a missing (default) parameter be done? - how would parameters to be passed to the debugger "of record" be passed in (named tuple? - sort of ugly) - would PYTHONBREAKPOINT be a global switch (I think yes), vs a `condition` default.
I have no dog in the fight, but to raise the possibility (?) of having PEP 553 implement simple conditional breakpoint processing.
Thanks for bringing this up Yarko. I think this could be done with the current specification for PEP 553 and an additional API from the various debuggers. I don’t think it needs to be part of PEP 553 explicitly, given the additional complications you describe above. Remember that both built-in breakpoint() and sys.breakpointhook() accept *args, **kws, and it is left up to the actual debugger API to interpret/accept those additional arguments. So let’s say you wanted to implement this behavior with pdb. I think you could do something as simple as: def conditional_set_trace(*, condition=True): if condition: pdb.set_trace() sys.breakpointhook = conditional_set_trace Then in your code, you would just write: def foo(value): breakpoint(condition=(value < 0)) With the IPython gist you referenced, you wouldn’t even need that convenience function. Just set sys.breakpointhook=conditional_breakpoint.breakpoint_ and viola! You could also PYTHONBREAKPOINT=conditional_breakpoint.breakpoint_ python3.7 … and it should Just Work. Cheers, -Barry
On Wed, Oct 4, 2017 at 7:50 PM, Barry Warsaw <barry@python.org> wrote:
On Oct 4, 2017, at 20:22, Yarko Tymciurak <yarkot1@gmail.com> wrote:
I've recently started using a simple conditional breakpoint in ipython, and wonder if - in addition to Nick Coghlan's request for the env 'PYTHONBREAKPOINT' (boolean?), it would make sense (I _think_ so) to add a condition parameter to the breakpoint() call. This does raise several questions, but it seems that it could make for a simple unified way to conditionally call an arbitrary debugger. What I found useful (in the contecxt of ipython - but general enough) you can see in this gist: https://gist.github.com/yarko/bdaa9d3178a6db03e160fdbabb3a9885
If PEP 553's breakpoint() were to follow this sort of interface (with "condition"), it raises a couple of questions: - how would a missing (default) parameter be done? - how would parameters to be passed to the debugger "of record" be passed in (named tuple? - sort of ugly) - would PYTHONBREAKPOINT be a global switch (I think yes), vs a `condition` default.
I have no dog in the fight, but to raise the possibility (?) of having PEP 553 implement simple conditional breakpoint processing.
Thanks for bringing this up Yarko. I think this could be done with the current specification for PEP 553 and an additional API from the various debuggers. I don’t think it needs to be part of PEP 553 explicitly, given the additional complications you describe above.
Remember that both built-in breakpoint() and sys.breakpointhook() accept *args, **kws, and it is left up to the actual debugger API to interpret/accept those additional arguments. So let’s say you wanted to implement this behavior with pdb. I think you could do something as simple as:
def conditional_set_trace(*, condition=True): if condition: pdb.set_trace()
sys.breakpointhook = conditional_set_trace
Then in your code, you would just write:
def foo(value): breakpoint(condition=(value < 0))
With the IPython gist you referenced, you wouldn’t even need that convenience function. Just set sys.breakpointhook=conditional_breakpoint.breakpoint_ and viola!
You could also PYTHONBREAKPOINT=conditional_breakpoint.breakpoint_ python3.7 … and it should Just Work.
Thanks Barry - yes, I see: you're correct. Thanks for the pep! - Yarko
Cheers, -Barry
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ yarkot1%40gmail.com
Yarko, there's one thing I don't understand. Maybe you can enlighten me. Why would you prefer breakpoint(x >= 1000) over if x >= 1000: breakpoint() ? The latter seems unambiguous and requires thinking all around. Is there something in iPython that makes this impractical? -- --Guido van Rossum (python.org/~guido)
apologies - I didn't "reply all" to this. For the record: I made an argument (in reply) about interactive tinkering, and setting "condition", and Guido replied essentially that "if condition: breakpoint()" is just as good for tinkering... a condition parameter to debuggers is not useful, and not as explicit. Yes - agreed (and the `gist` which I tinkered w/ one day - I've now discarded ;-). Thanks, Guido! - Yarko On Wed, Oct 4, 2017 at 9:12 PM, Guido van Rossum <guido@python.org> wrote:
Yarko, there's one thing I don't understand. Maybe you can enlighten me. Why would you prefer
breakpoint(x >= 1000)
over
if x >= 1000: breakpoint()
?
The latter seems unambiguous and requires thinking all around. Is there something in iPython that makes this impractical?
-- --Guido van Rossum (python.org/~guido)
participants (5)
-
Barry Warsaw
-
Glenn Linderman
-
Guido van Rossum
-
Terry Reedy
-
Yarko Tymciurak