Vedran Čačić added the comment: Well, I don't know how good this comment box is for a pdb tutorial. :-) And I learned it a long time ago, so I don't really remember how it is to not know it. :-/ The main reason I love it is purely sentimental: it reminds me of those silly text-based adventure games. If you played Zork, you'll feel right at home. :-D
(If you want a more "ordinary" introduction, yet refreshingly different than the boring stdlib manpage, visit https://pythonconquerstheuniverse.wordpress.com/2009/09/10/debugging-in-python/.) You put "import pdb; pdb.set_trace()" (or "__import__('pdb').set_trace()" if you hate semicolons more than dunders:) before the line you want to set a breakpoint in. Then you run the program normally. When it hits a breakpoint, it gives you a (Pdb) prompt, and you can look around. (Alternatively, when you get an exception, just "import pdb; pdb.pm()" for a post-mortem debugger. All the stack frames that lead to exception are preserved with all their local variables, nicely inspectable. Beautiful.:) `u` and `d` (up and down) are the elevator buttons that move you along the frame stack: u towards earlier (outer) calls, d towards later (inner) calls. `w` (where) lets you see which "floor" you're on. On every floor, `p` (print) and `pp` (prettyprint) give you information about various objects you see, like "examine" in text adventures :-). `!` lets you execute an arbitrary Python statement (! is not needed in most cases, but it's good to make a habit of writing it) _inside the current stackframe_ (yes, everything is live:). `interact` gives you a full Python shell attached on the current frame. `l` lists a few lines around your current place, `ll` lists the whole function (or another meaningful whole). `a` gives you the arguments for the current function call. `s` and `r` are the "in" and "out" commands, allowing you to step inside and return from currently called function. `n` is just "next", meaning "execute current line and show me the next one". Unfortunately, `n` has no inverse (you cannot undo an executed statement), but `j` is a (limited) goto. If you go too far into a strange land, `run` restarts the program from the beginning. pdb always shows the line it's about to execute (it's not yet executed). Just pressing Enter repeats the last given command (in case of `l`, keeps listing onwards). `c` means quit the debugger and continue executing program normally. `q` means quit the debugger and program altogether. There are many more commands, but those are kinda basic ones to know your way around. Ok, now what I've done with IDLE. You mentioned configdialog.py, line 1066. I go there and find a function def LoadKeyCfg(self): Ok, that's obviously the function I have to trace. As the first statement in that function, I put "import pdb; pdb.set_trace()" call and save the file. Then I go to command prompt, and start IDLE. I go to Options > Configure IDLE, and sure enough, at my command prompt there is > c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\configdialog.py(1069)LoadKeyCfg() -> self.keysAreBuiltin.set(idleConf.GetOption( (Pdb) a Pdb prompt. I type l and Enter, to see where I am in the code. (Pdb) l 1064 self.SetHighlightTarget() 1065 1066 def LoadKeyCfg(self): 1067 import pdb; pdb.set_trace() 1068 ##current keys type radiobutton 1069 -> self.keysAreBuiltin.set(idleConf.GetOption( 1070 'main', 'Keys', 'default', type='bool', default=1)) 1071 ##currently set keys 1072 currentOption = idleConf.CurrentKeys() 1073 ##load available keyset option menus 1074 if self.keysAreBuiltin.get(): #default theme selected (Pdb) Ok, so it's going to set a Tkinter variable (I know by seeing ".set", but there is also a `whatis` command if you want to see the type of something). I say n to execute it (twice because it's two lines), and then (Pdb) p self.keysAreBuiltin.get() False (Pdb) So far so good. Keys aren't builtin. (Pdb) n > c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\configdialog.py(1072)LoadKeyCfg() -> currentOption = idleConf.CurrentKeys() Ok, now it's going to set CurrentKeys. (Pdb) n ... (Pdb) p idleConf.CurrentKeys() 'IDLE Classic Windows' Ok, this shouldn't happen. Let's goto it again (hoping there aren't many sideeffects:) and step into it this time. (Pdb) l 1069 self.keysAreBuiltin.set(idleConf.GetOption( 1070 'main', 'Keys', 'default', type='bool', default=1)) 1071 ##currently set keys 1072 currentOption = idleConf.CurrentKeys() 1073 ##load available keyset option menus 1074 -> if self.keysAreBuiltin.get(): #default theme selected 1075 itemList = idleConf.GetSectionList('default', 'keys') 1076 itemList.sort() 1077 self.optMenuKeysBuiltin.SetMenu(itemList, currentOption) 1078 itemList = idleConf.GetSectionList('user', 'keys') 1079 itemList.sort() (Pdb) So it's line 1072. (Pdb) j 1072 > c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\configdialog.py(1072)LoadKeyCfg() -> currentOption = idleConf.CurrentKeys() (Pdb) s --Call-- > c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\config.py(368)CurrentKeys() -> def CurrentKeys(self): (Pdb) l 363 364 def CurrentTheme(self): 365 "Return the name of the currently active text color theme." 366 return self.current_colors_and_keys('Theme') 367 368 -> def CurrentKeys(self): 369 """Return the name of the currently active key set.""" 370 return self.current_colors_and_keys('Keys') 371 372 def current_colors_and_keys(self, section): 373 """Return the currently active name for Theme or Keys section. (Pdb) n > c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\config.py(370)CurrentKeys() -> return self.current_colors_and_keys('Keys') (Pdb) s --Call-- > c:\users\veky\appdata\local\programs\python\python36\lib\idlelib\config.py(372)current_colors_and_keys() -> def current_colors_and_keys(self, section): (Pdb) A few `n`s, and we have a culprit. `ll` to see a whole function and confirm our suspicion, and a final test: make a new color theme. It works. Victory! :-) ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue27821> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com