The `embed` Debugging Trick in Python and Ctrl+Z
Insert the breakpoint
There’s a useful trick for efficiently debugging Python code. Say if you have a loop like the one below, how to interactively access the list
l at each loop step?
l = 
You can insert a “breakpoint” as follows.
Then you run
python test.py in the shell, and an interactive environment will be prompted out like this:
colin ❯ python test.py
The program stops at the position of
embed(), and you can access variables visible at this point, like:
In : l
You can also execute most kinds of Python code here, like:
In : l.append(100)
You can use
quit to continue running the program, and the program will stop at the next breakpoint if there’s any. Ctrl+D is equivalent to this.
In : quit
Exit the program
Sometimes you insert
embed() inside a loop that will repeat many times, and you just want to exit running the program at some time. But you will find both Ctrl+C and Ctrl+D do not work here, so we can just close the shell and the process will be terminated. :)
Closing the shell works, but we have something better. Say now you are in the interactive environment provided by
embed. You can press Ctrl+Z here, and then you are back to your shell and see something like below.
In : # press Ctrl+Z here!
BUT we’re NOT done yet! Ctrl+Z just sends the “terminal stop” signal (SIGTSTP) to the foreground running process. The process will not take any more CPU resources, but it still occupies memory and ISN’T dead yet. You can even use
fg to bring it back!
colin ❯ fg
To terminate the process completely, you need to use
kill -9 command, which sends a SIGKILL signal indicating to a service to shutdown immediately. In our case, you can execute
kill -9 %1 to terminate the process just suspended by Ctrl+Z.
%1 means “job number 1” in the current shell. You can run
jobs to list all jobs in the current shell, like:
colin ❯ ipython # run ipython in the shell first
Combining Ctrl+Z and
kill -9 is also useful for stopping a process immediately. Because sometimes, after
Ctrl+C, the process will do some post-processing which may take a long time. Then you can use this way to stop it right now.
Deactivate the current
Thanks to my friend @Leo‘s reminder, we can use
%kill_embedded in the ipython interactive environment to deactivate the current
embed() but keep others working. For example, in the program below, after stopping at the
embed() in the first loop for 2 times, we can do
%kill_embedded with confirming it and
quit to skip the remaining ones in the first loop, while the
embed() in the second loop still works so we will stop there.
Execuation log in shell:
colin ❯ python test2.py
What is effect of CTRL + Z on a unix\Linux application