Search code examples
pythonlinuxbashctrl

Python/Calling python scripts within bash terminal: What exactly happens when user presses Ctrl-C?


I need help with controlling a python script. I want to run a script that controls two robots. A routine consists of a series of motions which either move the arm or move the gripper. The form of the code is as follows:

def robot_exec():
  # List of robot arm poses:
  *many_many_lines_of_position_vectors*

  # List of robot gripper poses:
  *open position*
  *close position*

  while 1:
    *Call a function that moves the robot arm(s) to a position on the list*
    *Call a function that moves the robot gripper(s) to a position on the list*
    *continue calling functions many times until the desired routine is complete*
    n = raw_input("Restart the routine? (Y/N)")
    if n.strip() == 'n' or 'N':
      break
    elif n.strip() == 'y' or 'Y':
      continue
    else:
      print "Invalid input. Exiting..."
      break

If the routine is complete (i.e. every function was called), it asks if I want to restart, and if I choose yes, behaves as normal, which is good.

But, if I press ctrl-C in the middle of the routine, the message "Restart the routine?" still pops up and asks for input, and I don't want that. What I want is either one of the following:

  1. if and only if the user presses ctrl-C, completely exit everything, no questions asked.
  2. if and only if the user presses ctrl-C, return the robots to home position (defined in that list of arm poses) and then completely exit everything.

My main question is, how does ctrl-C actually work? I thought it would just exit the script but in actuality it still prints stuff and asks for input. A subset of that broad question is, how can I just get the desired behavior (completely exit everything when pressing ctrl-C)?

I realize this is a clunky way of doing what I need the robots to do, but it is the best way I can think of with my limited knowledge of python.


Solution

  • The comments/answers about signals are technically correct (on UNIX), but in Python the CTRL+C handling is neatly wrapped away from you. What happens in a Python program is that at the point where you press CTRL+C, a KeyboardInterrupt exception is raised.

    Now, your problem seems to be in the code that you have removed from the listing, i.e., in the "calling robot routines" part. That code catches the KeyboardInterrupt.

    I guess either your code or library code that you call does something like:

    try:
        # some long running code
        # ...
    except:
        # something, or just pass
    

    Note the naked except:. Naked excepts are almost always a bad thing. Instead you or the library should do:

    try:
        # some long running code
        # ...
    except Exception:
        # something to fix the situation
    

    Using except Exception: does not catch the KeyboardInterrupt exception, which will let you handle it appropriately, or just let the program exit. Have a look at the Exception class hierarchy.