Why does import pdb; pdb.set_trace trigger two dif

2019-03-06 10:56发布

问题:

This is a follow-up question to Stepwise debugging of selected Python code.

Why does import pdb; pdb.set_trace trigger two different debugging scenarios when called differently in Spyder?

Here's the edited sample code in the answer from Carlos Cordoba to the question mentioned above.

The code:

def foo():
    names = ['A', 'B', 'C']
    values = [11,12,13]

    i = 0
    import pdb; pdb.set_trace()
    for n in names:
        variable = str(n)  + ' = ' + str(values[i])
        print(variable)
        i += 1      
foo()

Scenario1 - Run file (F5), Continue Execution until next breakpoint (F12) and Run Current Line (F10)

This procedure works just fine. Let me just explain how for the sake of context:

Run file (F5) highlights line 2:

Proceeding with Continue Execution until next breakpoint (F12) takes you directly to line 8. Also notice in the screenshot below that the Variable explorer is populated with the variables i, names and values. Other variables are added and updated as you go through the rest of the code with Run Current Line (F10):

Or you could Continue Execution until next breakpoint (F12) and finish the procedure that way. Doing the former all the way down to foo() clears the variable explorer, prints --Return-- in the ipdb debugger, and exits the debugger.

And I guess I should just go with this way of doing things every time, but I'm very interested in the other options of running code that Spyder offers as well. And I'm particularly fond of defining and running cells with #%% and Ctrl+Enter.

Scenario 2 - Ctrl+Enter in a cell that includes the entire code

Ctrl+Enter within the cell highlights line 8, and populates the Variable Explorer:

Proceeding with Continue Execution until next breakpoint (F12) clears the variable explorer and exits the debugger just like before:

And that's fine too, but here's my case:

Scenario 3 - Running and debugging multiple cells

When I'm debugging fragments of code of bigger data science projects, I often end up defining some variables one place, and wanting to debug functions that use these variables as input somewhere else. And that's why I often end up in the situation below, where I've defined the variables in one cell, and have a For Loop using the same variables in another cell:

Cell that contains variables

Cell that contains For Loop

But hitting Ctrl+Enter and proceeding with Run Current Line (F10) triggers a messy situation within interactiveshell.py:

And now, the questions:

  1. What's going on here?
  2. Can this be avoided?
  3. Why isn't it possible to debug cells (or highlighted code + f9) like this?

Thank you for any suggestions!

回答1:

(Spyder maintainer here) I think the problem is you're trying to evaluate cells inside the scope of a function. In this case all variables are local to the scope, so you can't evaluate foo in pieces, which is what you're trying to do with our cells.

To achieve what you want, you could use a class instead. That would allow you to save your data in variables shared by all methods in the class and to define the functions/methods you want to manipulate those data. A class would also allow you to have data and functions/methods neatly encapsulated, i.e. without being defined in the global scope of your code.

With that, you could simply run a cell that calls the method you want to debug. In the example you posted above, this will be

# %%
class Foo:
    def __init__(self):
        self.names = ['A', 'B', 'C']
        self.values = [11,12,13]

    def manipulation(self):
        i = 0
        import pdb; pdb.set_trace()
        for n in self.names:
            variable = str(n)  + ' = ' + str(self.values[i])
            print(variable)
            i += 1      

f = Foo()

# %%
f.manipulation()

This allows me to debug the workings of the manipulation method without problems.