Windows – How to pass Ctrl+C to script called from batch job

batch filecommand lineinterruptswindows

I am trying to avoid the effects of pressing Ctrl+C in a batch file somewhat similarly to How to supress "Terminate batch job (Y/N)" confirmation?. However, in my case, I want the signal to be handled by my underlying script. My batch file looks like this:

@ECHO off
setlocal
set "script_path=%~dp0"
set "script_path=%script_path%myscript.py"
python "%script_path%" %*
endlocal

I would like to be able to hit Ctrl+C and handle it as a KeyboardInterrupt error in myscript.py instead of immediately terminating the process. Right now, if I press Ctrl+C, I get:

forrtl: error (200): program aborting due to control-C event
Image              PC        Routine            Line        Source
libifcoremd.dll    0FCA7CB8  Unknown               Unknown  Unknown
KERNELBASE.dll     76411C99  Unknown               Unknown  Unknown
KERNEL32.DLL       74A68484  Unknown               Unknown  Unknown
ntdll.dll          77C2305A  Unknown               Unknown  Unknown
ntdll.dll          77C2302A  Unknown               Unknown  Unknown
Terminate batch job (Y/N)?

I have tried the following options:

  1. Replace python "%script_path%" %* with start python "%script_path%" %*. This starts a new shell, which is actually nice with what I am trying to do. Standard input appears to work properly in the new shell. However Ctrl+C has the same effect as before, and the new shell dies immediately. Appending an exit command to the end of the batch file appears to have no effect either.
  2. Replace python "%script_path%" %* with start /b python "%script_path%" %*. This just starts the job in the background in the same shell. Ctrl+C still just kills the job, and now standard input does not appear to work correctly.

Additional note:

My Python script does need to read user input from sys.stdin once in a while. The script reads some input, then processes it in a way that allows the user to hit Ctrl+C. The idea is to do something meaningful in the except KeyboardInterrupt: clause, rather than just watch the script die.

Best Answer

Ctrl-C is SIGINT so you can catch it by using the signal module inside you python script:

import signal
import time

def handler(signum, frame):
    print 'Got Ctrl-C'
    #you code handling the Ctrl-C

signal.signal(signal.SIGINT, handler)
# your code

Keep in mind that there was a bug in Python 2.7 for Windows, that was marked as Won't fix, so you should use Python 3.3+.

Related Question