Skip to content
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

Easier way to set_trace #109

Open
asmeurer opened this issue Feb 25, 2014 · 13 comments · May be fixed by #246
Open

Easier way to set_trace #109

asmeurer opened this issue Feb 25, 2014 · 13 comments · May be fixed by #246

Comments

@asmeurer
Copy link
Collaborator

We should make it so import pudb.b does the same thing as import pudb;pudb.set_trace(). The latter is too much to type. Are you OK with the name b? If so, I'll implement this.

@inducer
Copy link
Owner

inducer commented Feb 26, 2014

There's already pu.db which works if you start your script with -m pudb. I'm not categorically opposed, but you'd have to convince me that this serves a valid use case.

Also, what about repeated imports? Will this trigger properly if you import the same thing twice?

@asmeurer
Copy link
Collaborator Author

I didn't know about pu.db. But if I wanted to start my code with -m pudb, I would just set a breakpoint.

set_trace does the right thing when called multiple times. So I can't imagine this would work differently. b.py will probably be exactly the same as set_trace, except maybe jumping a different number of frames so that we don't break in pudb itself. I haven't tested any of it yet, though, so I could be wrong.

@inducer
Copy link
Owner

inducer commented Feb 26, 2014

I don't think repeated imports work. I'll buy it if you check. :)

@asmeurer
Copy link
Collaborator Author

I'll play around with it tomorrow.

@asmeurer
Copy link
Collaborator Author

Ah, I see what you mean now. Second imports won't trigger. We may have to register an import hook for this to work.

And speaking of import hooks, in Python 3, all the import machinery is implemented in Python, meaning a single sys._getframe().f_back will just take you somewhere inside Python's importlib. But that's pretty easy to fix I think. Just go back until you escape from importlib.

@asmeurer
Copy link
Collaborator Author

Import hooks may not help. The sys.modules cache is used before hooks are used, if I understand the documentation correctly. I played around with them and couldn't get them to work. I also tried monkeypatching sys.modules, but that didn't work either.

I think I am able to get something that works by monkey-patching __builtins__.__import__. I haven't gotten the right f_back logic yet, though, which seems tricky at least in Python 3 because all the import logic is written in Python.

asmeurer added a commit to asmeurer/PuDB that referenced this issue Feb 27, 2014
This lets you just run

import pudb.b

to trigger a set_trace(). It works by monkey-patching
__builtins__.__import__. It does not yet work in Python 3.3, due to the new
import mechanism.

See inducer#109.
@asmeurer asmeurer mentioned this issue Feb 27, 2014
@asmeurer
Copy link
Collaborator Author

OK, the version in #110 works in Python 2, and probably Python < = 3.2. I think I just need to fiddle with the f_backs a bit in Python 3.3 to dodge the importlib stuff.

__builtins__.__import__ is only monkeypatched if you import pudb.b.

@asmeurer
Copy link
Collaborator Author

asmeurer commented Mar 7, 2014

By the way, I just noticed that all this importlib stuff from Python 3 is there in the stack even in normal set_trace situations.

@inducer
Copy link
Owner

inducer commented Mar 8, 2014

Sorry, not sure I'm following. Can you explain what you mean? Thx!

@asmeurer
Copy link
Collaborator Author

asmeurer commented Mar 8, 2014

$cat test1.py
from pudb import set_trace; set_trace()
$cat test2.py
import test1

Then, with Python 3.3, run python test2.py. Here is my stack:

screenshot 2014-03-08 15 49 09

Maybe it's a bug in Python that the frames aren't being removed as well as they should be. I don't know.

@inducer
Copy link
Owner

inducer commented Mar 9, 2014

I agree, that's weird. Just to clarify, that's upon hitting the set_trace? What happens if the set_trace is on a separate line?

@asmeurer
Copy link
Collaborator Author

asmeurer commented Mar 9, 2014

Yes, it's the set_trace(), not the import of set_trace from pudb (which is irrelevant).

The problem is that the set_trace() is called in the middle of an import, so you get all the import machinery in the stack. This only happens in Python 3.3 because the import machinery was rewritten in Python (as a frozen module) in that version (in previous versions, it was written in C and didn't take up any stack frames, or at least none visible to a tracing debugger).

There is actually a second bug here, which is that the UI doesn't render correctly if you move up to the frame from the frozen module.

screenshot 2014-03-08 19 01 55

I'm assuming this happens with any frozen module. PuDB should just remove frozen modules from the stack trace, or at least prevent from selecting them, as they aren't very useful (I guess removing them could be a bad idea because there is useful information there).

Feel free to split this into a separate issue or issues.

@inducer
Copy link
Owner

inducer commented Mar 9, 2014

Well, it definitely shouldn't destroy the UI. I'd argue these modules should stay in the stack trace, but we probably shouldn't attempt to render their source.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants