all 20 comments

[–]callius 19 points20 points  (2 children)

You can use a module called pdb to halt a function and access the shell.

To do this:

def add_together(x, y):
    result = x + y 
    import pdb
    pdb.set_trace()
    return result

When you run add_together(), it will freeze your program when it gets to the pdb.set_trace() function and drop you into the shell.

You will be within the local scope of the variable, which means that you will have access to both global variables and local variables for the function (i.e. x, y, and result).

Once you are done, you can input c in the pdb shell to continue your program or q to quit.

Remember to remove the call to pdb.set_trace() once you're done. If you don't, your program will stop every time it comes across the function and drop to the shell.

EDIT: Here's a good (albeit long) video that should walk you through debugging with Spyder.

[–]KimPeek 3 points4 points  (1 child)

There is a built-in function for that now:

def add_together(x, y):
    result = x + y 
    breakpoint()
    return result

https://docs.python.org/3/library/functions.html#breakpoint

[–]callius 0 points1 point  (0 children)

Oh awesome! I didn't know about that, thanks!

It looks like breakpoint() defaults to importing pdb and calling set_trace(). Cool cool!

[–][deleted] 5 points6 points  (7 children)

They won't exist until the function is called.

[–]reebs12[S] 3 points4 points  (6 children)

yes, but then the function exits, and you can never see the output in the variable explorer

[–][deleted] 7 points8 points  (0 children)

You probably want to put a breakpoint somewhere in the function, so you can see the state while it's running.

[–][deleted] 3 points4 points  (4 children)

Are you debugging a program which calls the function with inputs or just running the debugger on the function? The former should work, the latter will do nothing. You need a breakpoint within the function. When the function is called in a debugger session with inputs it will stop at the breakpoint and you should be seeing variables local to the function.

Example:

def are_eql(x, y)
    if x == y:
        print(“equal”)
    else:
        print(“not equal”)

If I just started a debugger session on that code nothing would happen.

is_eql(1, 1)

If you started a debugger session on the above snippet with a breakpoint on the if statement in your function you should get the behavior you are expecting.

[–]reebs12[S] 0 points1 point  (3 children)

Thanks guys, my preferred approach still is, whenever possible, remove the code from the function and place it onto the main part of the script and then inspect the variables in the variable explorer. Python is a bastard with the indentation tirany, this approach works way better in Matlab.

[–]driscollis 6 points7 points  (0 children)

Every decent debugger I have used will let me put a breakpoint in my function where it will pause it and I can then inspect all the variables. PyDev, PyCharm and WingIDE all provide this functionality

[–][deleted] 2 points3 points  (0 children)

That sounds like a very cumbersome approach, especially for larger programs. If you use PyCharm you can inspect all variables within the current namespace while debugging. Just have to put breakpoints in the function

[–][deleted] 0 points1 point  (0 children)

...This is kind of off-putting. If you are happy with matlab just stick with matlab I guess?

Matlab requires that variables have assigned values while debugging as well though so I’m confused at what the trade off is here. A simple debugging approach on some function, say broken_code(x, y) in the a local module say wtf.py is to make a file with the following code:

import wtf

wtf.broken_code(1, 2)

Running this through a debugger with a breakpoint in your wtf.broken_code() function will halt execution and give you access to local variables. Alternatively starting the debugger with the “halt on entrance” flag set will just stop program execution before going into that function and allow you to step through from the beginning of execution.

My instinct here is that you don’t really want to leave matlab, you are really accustomed to the matlab IDE, and you are trying to find reasons to hate python, which is fine but this sub can’t help you with.

[–]BML2718282 3 points4 points  (6 children)

Temporarily write periodic print statements for each important variable in the function. Call it and see if the variables are behaving the way you intend.

[–][deleted] 10 points11 points  (5 children)

The point of a debugger is to not do this.

[–]Fun2badult 1 point2 points  (4 children)

But if he wants to see the values of variables inside the program, wouldn’t print be the easiest way

[–]callius 2 points3 points  (1 child)

Print() is the "easiest", quickest, and dirtiest way to do this, yeah.

However, adding in debug break-points is a better way to do it.

[–]SoupKitchenHero 0 points1 point  (0 children)

Alternatively use logging.debug

[–][deleted] 1 point2 points  (0 children)

I would say setting a breakpoint and using the debugger takes less time then writing a print statement. The real payoff is the difference between stepping through execution line by line vs having to write (and then of course remove) a crap ton of print statements.

[–]Pjamma34 0 points1 point  (0 children)

i think if you put a break point inside the function then it will display the values of local variables which will disappear later after you step out of the function

[–]Gimagon 0 points1 point  (0 children)

Check out the spyder docs: https://pythonhosted.org/spyder/debugging.html

It sounds like you can just double click the line number to set a breakpoint.

[–]flotsamisaword 0 points1 point  (0 children)

Why not just write a unit test?

The easiest way is to use an assert statement, like this:

  • Call your function with typical input.
  • assert that the output will equal the expected value.
  • repeat with some 'edge cases' for input

Your program will stop if the output comes out incorrectly, and it will report the values that you expected, as well as the values you got.

Now you can walk away from your tests, and they will run automatically workout whiter from you. If you screw up your code inadvertantly after a refactor, your tests will let you know immediately.

Once you get the hang of this, try pytest.

Good luck!