I have a long code that sometimes I do not want to execute all of the code, but just stop at a certain line. To stop the execution of a code at a line, I do the following:
print('Stop here: Print this line')
quit()
print('This line should not print because the code should have stopped')
The right answer is only the first line should print. When I use quit(), quit , exit(), or exit both lines print. When I use import sys and then sys.exit() I get the following error message
An exception has occurred, use %tb to see the full traceback.
SystemExit
C:\Users\user\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3351:
UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit:
use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
How can I perform this task of stopping execution at a line?
In case you are trying to debug the code and may want to resume from where it stopped, you should be using pdb instead
print('Stop here: Print this line')
import pdb; pdb.set_trace()
print('This line should not print because the code should have stopped')
When you execute it, the interpreter will break at that set_trace() line. You will then be prompted with pdb prompt. You can check the values of variable at this prompt. To continue execution press c or q to quit the execution further. Check other useful command of pdb.
It appears that you would like to stop the code at a certain point of your choosing
To do this I found two possible ways within your constraints.
One is that you simply write
raise Exception("Finished code")
This would allow you to stop the code and raise your own exception and write whatever exception you so choose.
However, if you would like to not have any exception whatsoever then I would point you to this link: https://stackoverflow.com/a/56953105/14727419.
It seems to be an issue related to iPython, as seen here.
If you don't wish to use the solution provided there, and don't mind forcefully killing the process, you can do:
import os
os.system('taskkill /F /PID %d' % os.getpid())
For your debugging purposes it fine to use the builtin debugger pdb. The following link gives a tutorial how to set it up: Debug Jupyter
This is what I have to prevent unintentional execution of the Tests section at the bottom of the pipeline:
import pdb
# this line should capture the input, temporarily
# preventing subsequent notebook cells from being executed
pdb.set_trace()
# this line causes pdb to exit with an error, which is required
# to stop subsequent cells from execution if user fails to type
# "exit" in pdb command line and just presses the Stop button in the Notebook interface
raise Error("This line should fail to prevent cells below from being executed regardless of how pdb was exited!")
Related
I like to paste hunks of code into an ipython window during development and debug. I also have a situation where I want to stop execution if a condition happens:
if condition:
<stop running>
Solutions like sys.exit() appear to exit all the way out of ipython back to a terminal prompt. Is there another way? At the moment I do this:
if condition:
fjklsd;
Which gives an error and returns to the ipython prompt, but is pretty ugly too.
You can raise this exception raise KeyboardInterrupt
Is there a proper way to create a script that loops through files in a folder and executes a subprocess that can be externally killed with Ctrl C? I have something like the following embedded in a pipeline and cannot Ctrl C it from the command line when the main process is killed.
Example script:
import subprocess
import os
import sys
input_directory = sys.argv[1]
for file in os.listdir(os.path.abspath(input_directory)):
output = file + "_out.out"
command = ['somescript.py', file, output]
try:
subprocess.check_call(command)
except:
print "Command Failed"
I would then execute program:
Example_script.py /path/to/some/directory/containing/files/
While it is looping, if I see the command failed, I want use Ctrl C. However, it fails and continues to run additional subprocesses despite the main script has been destroyer with Ctrl C. Is there a proper way to write something like this that can kill the childs (additional subprocess) with Ctrl C?
Any help, or pointing me in the direction is appreciated greatly. I am currently looking for a good method to do.
What you have in your try/except block is too permissive, such that when Ctrl+C is pressed, the KeyboardInterrupt exception is also handled by that same exception handler as the one that print "Command Failed", and as that is now properly handled there, the flow of the program is continued through the for loop. What you should do is:
Replace except: with except Exception: so that the KeyboardInterrupt exception will not be trapped, such that any time Ctrl+C is pressed the program will terminate (including subprocesses that isn't stuck in some non-terminatable state);
After the print statement, break out of the loop to prevent further execution from happening, if that is the intended behavior that you want this program to do.
You can catch KeyboardInterrupt, that way you can deal with Ctrl+C in whatever manner you want.
import subprocess
import os
import sys
input_directory = sys.argv[1]
for file in os.listdir(os.path.abspath(input_directory)):
output = file + "_out.out"
command = ['somescript.py', file, output]
try:
subprocess.check_call(command)
except KeyboardInterrupt as e:
print "Interrupted"
sys.exit(1)
except:
print "Command Failed"
However I agree with the other posters in that your exception is too vague, and you should be more specific in what can and can't fail.
I think Ctrl + Z can also help you to push the execution to background and suspended.
I have a bug in my program and want to check it out using debug. In my IDE (WingIDE) I have a debug functionality. But I can not use that call the program from shell. So I use the Python module pdb. My application is single threaded.
I have looked into Code is behaving differently in Release vs Debug Mode but that seems something different to me.
I limited it down this the following code.
What I did :
I created a short method it will only be called when using no IDE.
def set_pdb_trace():
run_in_ide = not sys.stdin.isatty()
if not run_in_ide:
import pdb; pdb.set_trace() # use only in python interpreter
This work fine, I used it in many situations.
I want to debug the following method :
import sys
import os
import subprocess32
def call_backported():
command = 'lsb_release -r'
timeout1 = 0.001 # make value too short, so time-out will enforced
try:
p = subprocess32.Popen(command, shell=True,
stdout=subprocess32.PIPE,
stderr=subprocess32.STDOUT)
set_pdb_trace()
tuple1 = p.communicate(input=b'exit %errorlevel%\r\n', timeout=timeout1)
print('No time out')
value = tuple1[0].decode('utf-8').strip()
print('Value : '+ value)
except subprocess32.TimeoutExpired, e:
print('TimeoutExpired')
Explanation.
I want to call subprocess with a timeout. For Python 3.3+ it is build in, but my application has be able to run using Python2.7 also. So I used https://pypi.python.org/pypi/subprocess32/3.2.6 as a backport.
To read the returned value I used How to retrieve useful result from subprocess?
Without timeout, setting timeout to f.e. 1 sec the method works as expected. The result value and 'No time out' is printed.
I want to enforce a timeout so I set the timeout very short time 0.001 . So now only 'TimeoutExpired' should be printed.
I want to execute this is shell.
When if first comment out line #set_pdb_trace() 'TimeoutExpired' is printed, so expected behaviour.
Now I uncomment set_pdb_trace() and execute in shell.
The debugger displays, I press 'c' (continue) and 'No time out' with the result is printed. This result is different then without debug. The generate output is :
bernard#bernard-vbox2:~/clones/it-should-work/unit_test$ python test_subprocess32.py
--Return--
> /home/bernard/clones/it-should-work/unit_test/test_subprocess32.py(22)set_pdb_trace()->None
-> import pdb; pdb.set_trace() # use only in python interpreter
(Pdb) c
No time out
Value : Release: 13.10
bernard#bernard-vbox2:~/clones/it-should-work/unit_test$
How is this possible? And how to solve?
You introduced a delay between opening the subprocess and writing to it.
When you create the Popen() object, the child process is started immediately. When you then call p.communicate() and try to write to it, the process is not quite ready yet to receive input, and that delay together with the time it takes to read the process output is longer than your 0.0.1 timeout.
When you insert the breakpoint, the process gets a chance to spin up; the lsb_release command doesn't wait for input and produces its output immediately. By the time p.communicate() is called there is no need to wait for the pipe anymore and the output is produced immediately.
If you put your breakpoint before the Popen() call, then hit c, you'll see the timeout trigger again.
After opening an interactive console while debugging using
code.interact(local=locals())
How can I resume code execution. I have checked the docs for the 'code' module and search stack overflow but cannot find anything.
It's the same way you exit any Python interpreter session: send an end-of-file character.
That's Ctrl-D on Linux or Ctrl-Z Enter on Windows.
If like me you always forget to hit Ctrl-D, you can wrap up your prompt in a try/except block:
try:
code.interact(local=locals())
except SystemExit:
pass
I have the following python code:
os.system("C:/Python27/python.exe C:/GUI/TestGUI.py")
sys.exit(0)
It runs the command fine, and a window pops up. However, it doesn't exit the first script. It just stays there, and I eventually have to force kill the process. No errors are produced. What's going on?
instead of os.system use subprocess.Popen
this runs a command and doesn't wait for it and then exits:
import subprocess
import sys
subprocess.Popen(["mupdf", "/home/dan/Desktop/Sieve-JFP.pdf"])
sys.exit(0)
note that os.system(command) like:
p = subprocess.Popen(command)
p.wait()
KeyboardInterrupts and signals are only seen by the process (ie the main thread). If your nested command hangs due to some kind of file read or write block, you won't be able to quit the program using any keyboard commands.
Why does a read-only open of a named pipe block?
If you can't eliminate the source of the disk block, then one way is to wrap the process in the thread so you can force kill it. But if you do this, you leave opportunity for half-written and corrupted files on disk.
I suggest using os._exit instead of sys.exit, as sys.exit doesnt quit a program but raises exception level, or exits a thread. os._exit(-1) quits the entire program
import sys ,subprocess
subprocess.Popen(["C:/Python27/python.exe", "C:/GUI/TestGUI.py"])
sys.exit(0)
Popen from subprocess module what you are looking for.