156

I have a python script that uses threads and makes lots of HTTP requests. I think what's happening is that while a HTTP request (using urllib2) is reading, it's blocking and not responding to CtrlC to stop the program. Is there any way around this?

3
  • 12
    I don't know why, but at least on OS X, using Control + Backslash causes it to terminate and you get a "python crashed" dialog... strange. Not really that useful info, thus it is a comment!
    – micmoo
    Commented Sep 1, 2009 at 20:18
  • 3
    Actually it works on all applications in Terminal...
    – micmoo
    Commented Sep 1, 2009 at 20:19
  • 1
    David Beazley has described how a Ctrl/C interrupt can turn a muli-threaded Python script into a CPU hog. It's touched on here (stackoverflow.com/questions/990102/…) with a link to Beazley's talk.
    – Ned Deily
    Commented Sep 2, 2009 at 7:09

14 Answers 14

223

On Windows, the only sure way is to use CtrlBreak. Stops every python script instantly!

(Note that on some keyboards, "Break" is labeled as "Pause".)

12
  • 11
    What is Break? How do I type it? Commented Sep 1, 2009 at 19:44
  • 8
    There should be a Pause_Break button on your keyboard
    – jonatron
    Commented Sep 1, 2009 at 20:10
  • 22
    What if there isn't? I'm on a Intel Macbook, and it doesn't have a very full-featured keyboard.
    – Bluu
    Commented Sep 24, 2010 at 22:03
  • 68
    On Linux you should use Ctrl-Shift-\ Commented Aug 17, 2013 at 14:04
  • 13
    ctrl+Z doesn't kill the script, it just hides it to the background and suspends it. You can type fg to recall it.
    – Shady Xu
    Commented Mar 21, 2014 at 3:20
113

Pressing Ctrl + c while a python program is running will cause python to raise a KeyboardInterrupt exception. It's likely that a program that makes lots of HTTP requests will have lots of exception handling code. If the except part of the try-except block doesn't specify which exceptions it should catch, it will catch all exceptions including the KeyboardInterrupt that you just caused. A properly coded python program will make use of the python exception hierarchy and only catch exceptions that are derived from Exception.

#This is the wrong way to do things
try:
  #Some stuff might raise an IO exception
except:
  #Code that ignores errors

#This is the right way to do things
try:
  #Some stuff might raise an IO exception
except Exception:
  #This won't catch KeyboardInterrupt

If you can't change the code (or need to kill the program so that your changes will take effect) then you can try pressing Ctrl + c rapidly. The first of the KeyboardInterrupt exceptions will knock your program out of the try block and hopefully one of the later KeyboardInterrupt exceptions will be raised when the program is outside of a try block.

2
  • 1
    This is a great answer to enable the most common "break" which is ctrl+c.
    – Xerion
    Commented Apr 21, 2016 at 19:09
  • 2
    Not for me. I have only a single except KeyboardInterrupt case and still it won't trigger, unless the application is waiting for user keyboard input. Windows completely ignores the Ctrl+C
    – Bersan
    Commented Feb 8, 2022 at 12:20
59

If it is running in the Python shell use Ctrl + Z, otherwise locate the python process and kill it.

5
  • 28
    ^Z --> [1]+ Stopped --> kill %1 to stop job #1 (or job %1 as bash puts it) Commented Sep 1, 2009 at 19:44
  • 30
    Worth adding to the answer that Ctrl+Z just pauses the process. Commented Aug 24, 2013 at 14:50
  • 4
    To elaborate on the above: Pausing the process keeps it around in memory and in your shell, it just prevents it from using CPU resources. Files, sockets, everything is still open and in use. In fact, typing fg will bring it right back. Commented Aug 12, 2016 at 14:29
  • 5
    Ctrl+Z is not the proper way to stop a python script and should be avoided unless you plan on resuming the paused process. Commented Jan 31, 2020 at 20:55
  • Ctrl+Z and Enter stop Python shell on Windows. Commented Mar 16, 2021 at 20:53
42

The interrupt process is hardware and OS dependent. So you will have very different behavior depending on where you run your python script. For example, on Windows machines we have Ctrl+C (SIGINT) and Ctrl+Break (SIGBREAK).

So while SIGINT is present on all systems and can be handled and caught, the SIGBREAK signal is Windows specific (and can be disabled in CONFIG.SYS) and is really handled by the BIOS as an interrupt vector INT 1Bh, which is why this key is much more powerful than any other. So if you're using some *nix flavored OS, you will get different results depending on the implementation, since that signal is not present there, but others are. In Linux you can check what signals are available to you by:

$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGEMT       8) SIGFPE       9) SIGKILL     10) SIGBUS
11) SIGSEGV     12) SIGSYS      13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGURG      17) SIGSTOP     18) SIGTSTP     19) SIGCONT     20) SIGCHLD
21) SIGTTIN     22) SIGTTOU     23) SIGIO       24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGPWR      30) SIGUSR1
31) SIGUSR2     32) SIGRTMAX

So if you want to catch the CTRL+BREAK signal on a linux system you'll have to check to what POSIX signal they have mapped that key. Popular mappings are:

CTRL+\     = SIGQUIT 
CTRL+D     = SIGQUIT
CTRL+C     = SIGINT
CTRL+Z     = SIGTSTOP 
CTRL+BREAK = SIGKILL or SIGTERM or SIGSTOP

In fact, many more functions are available under Linux, where the SysRq (System Request) key can take on a life of its own...

38

Ctrl+D Difference for Windows and Linux

It turns out that as of Python 3.6, the Python interpreter handles Ctrl+C differently for Linux and Windows. For Linux, Ctrl+C would work mostly as expected however on Windows Ctrl+C mostly doesn't work especially if Python is running blocking call such as thread.join or waiting on web response. It does work for time.sleep, however. Here's the nice explanation of what is going on in Python interpreter. Note that Ctrl+C generates SIGINT.

Solution 1: Use Ctrl+Break or Equivalent

Use below keyboard shortcuts in terminal/console window which will generate SIGBREAK at lower level in OS and terminate the Python interpreter.

Mac OS and Linux

Ctrl+Shift+\ or Ctrl+</kbd>

Windows:

  • General: Ctrl+Break
  • Dell: Ctrl+Fn+F6 or Ctrl+Fn+S
  • Lenovo: Ctrl+Fn+F11 or Ctrl+Fn+B
  • HP: Ctrl+Fn+Shift
  • Samsung: Fn+Esc

Solution 2: Use Windows API

Below are handy functions which will detect Windows and install custom handler for Ctrl+C in console:

#win_ctrl_c.py

import sys

def handler(a,b=None):
    sys.exit(1)
def install_handler():
    if sys.platform == "win32":
        import win32api
        win32api.SetConsoleCtrlHandler(handler, True)

You can use above like this:

import threading
import time
import win_ctrl_c

# do something that will block
def work():
    time.sleep(10000)        
t = threading.Thread(target=work)
t.daemon = True
t.start()

#install handler
install_handler()

# now block
t.join()

#Ctrl+C works now!

Solution 3: Polling method

I don't prefer or recommend this method because it unnecessarily consumes processor and power negatively impacting the performance.

    import threading
    import time

    def work():
        time.sleep(10000)        
    t = threading.Thread(target=work)
    t.daemon = True
    t.start()
    while(True):
        t.join(0.1) #100ms ~ typical human response
    # you will get KeyboardIntrupt exception
5
  • No, on Ubuntu, for both python 2.7 and 3.6, pressing ctrl + c doesn't quit but showing KeyboardInterrupt.
    – Rick
    Commented Mar 28, 2019 at 11:32
  • I like the thread example, but you don't need to use the SetConsoleCtrlHandler(). You can just do a try: time.sleep(5);except KeyboardInterrupt: break; in a while 1 loop. This works with any long delay for event handlers, but should be used with care when using polling and using not less time than: time.sleep(0.01).
    – not2qubit
    Commented Jan 3, 2021 at 8:07
  • Thanks. However, solution 1 would require end user awareness, which they probably do not have (unless they came here and read this answer :-) ). Solution 2 relies on platform specific API. I ended up using solution 3.
    – RayLuo
    Commented Sep 9, 2021 at 16:36
  • Ctrl+Fn+S worked for me, any idea how to configure this to be Ctrl+C?
    – Bersan
    Commented Feb 8, 2022 at 12:22
  • 1
    What could be </kbd> ?
    – Takamura
    Commented Jan 26, 2023 at 11:32
24

This post is old but I recently ran into the same problem of Ctrl+C not terminating Python scripts on Linux. I used Ctrl+\ (SIGQUIT).

1
  • Although it will cause a core dump, but it did stops the script, thanks
    – ospider
    Commented Dec 14, 2017 at 2:42
16

On Mac press Ctrl+\ to quit a python process attached to a terminal.

2
  • This is the only answer that works well for me on OSX in 2022 Commented Sep 6, 2022 at 8:57
  • Verified, this works on Mac OSX in 2022. Other method although a bit longwinded also works: ctrl+z --> [1]+ Stopped --> kill %1
    – binjiezhao
    Commented Dec 14, 2022 at 10:05
8

Capture the KeyboardInterrupt (which is launched by pressing ctrl+c) and force the exit:

from sys import exit

try:
    # Your code
    command = input('Type your command: ')

except KeyboardInterrupt:
    # User interrupt the program with ctrl+c
    exit()
3

On a mac / in Terminal:

  1. Show Inspector (right click within the terminal window or Shell >Show Inspector)
  2. click the Settings icon above "running processes"
  3. choose from the list of options under "Signal Process Group" (Kill, terminate, interrupt, etc).
1
  • Forcing the program to close using Alt+F4 (shuts down current program)
  • Spamming the X button on CMD for e.x.
  • Taskmanager (first Windows+R and then "taskmgr") and then end the task.

Those may help.

1

You can open your task manager (ctrl + alt + delete, then go to task manager) and look through it for python and the server is called (for the example) _go_app (naming convention is: _language_app).

If I end the _go_app task it'll end the server, so going there in the browser will say it "unexpectedly ended", I also use git bash, and when I start a server, I cannot break out of the server in bash's shell with ctrl + c or ctrl + pause, but once you end the python task (the one using 63.7 mb) it'll break out of the server script in bash, and allow me to use the git bash shell. enter image description here

1

For the record, what killed the process on my Raspberry 3B+ (running raspbian) was Ctrl+'. On my French AZERTY keyboard, the touch ' is also number 4.

0

On Mac, you use the good old Ctrl+c. Note: it is the Ctrl key, not Command or Option key.

0

The post is quite old but I faced the same issue this morning. On Mac OS, using pgrep Python to get the pid and then kill [pid] to kill the process worked fine.

Not the answer you're looking for? Browse other questions tagged or ask your own question.