I wrote an interactive python program with more than 100 functions which do various computations I'm interested in.
The user enters a function name at the input prompt, which is then executed with results either displayed as a return value or as a side effect. I want to be able to abort long running functions, via a control C, without killing the program.
This part I've accomplished. For example, as shown below, if a control-C is entered while function2(20) is running, anytime before it finishes, the function is aborted and the input prompt is displayed again.
However if I happen, by accident, to enter control-C at the input prompt, the program is killed. I don't want that to happen; rather I want to just return back to the input prompt. Since these two features are part of standard python interpreters, it should be possible to do what I want.
Here's a skeleton version of what I've done, called skeleton.
#!/Users/richard.gostanian/anaconda3/bin/python
import sys
import signal
import time
def trivial_function(n):
return n
def function2(n):
for i in range(1,n):
print(i)
time.sleep(1)
return n
while True:
entered2 = input("Enter function with arguments: ")
entered=entered2.strip() # remove preceding and trailing whitespace from entered2
if entered == 'q':
print()
quit()
elif entered == "": # go back to the input prompt
print()
continue
else:
try:
result=eval(entered)
print("\n {} = {} \n".format(entered,result))
continue
except KeyboardInterrupt:
print()
continue
Here is the output if you type control-C while function2(20) is running
Enter function: function2(20)
1
2
3
4
^C
Enter function:
And here is the output if you type control-C at the input prompt
Enter function: ^CTraceback (most recent call last):
File "/Users/richard/home/richard/bin/./skeleton", line 17, in <module>
entered2 = input("Enter function: ")
^^^^^^^^^^^^^^^^^^^^^^^^^
KeyboardInterrupt
bash >
How do I modify this to not kill the program in the second case?
Put try/except
around the entire loop body, not just the call to eval()
.
while True:
try:
entered2 = input("Enter function with arguments: ")
entered=entered2.strip() # remove preceding and trailing whitespace from entered2
if entered == 'q':
print()
quit()
elif entered == "": # go back to the input prompt
print()
else:
result=eval(entered)
print("\n {} = {} \n".format(entered,result))
except KeyboardInterrupt:
print()
You don't need all those continue
statements. A loop automatically continues unless the while
condition is false or you use break
to get out. You only need to use continue
if you want to skip over the rest of the loop body and start the next iteration, but there's nothing to skip over.