Search code examples
pythonpython-3.xsocketssettimeoutkeyboardinterrupt

How to catch KeyboardInterrupt from within socket.timeout exception handler?


I'm trying to develop a simple socket server that has a non-blocking accept (using settimeout) but I would like to be able to stop it using Ctrl-C (KeyboardInterrupt).

My code is this:

import socket

host = '127.0.0.1'
port = 5000

s = socket.socket()
s.settimeout(1)
s.bind((host, port))
s.listen(1)
print('Server started')
while True:
    try:
        conn, addr = s.accept()
    except socket.timeout:
        pass
    except Exception as exc:
        print(str(exc))
        print('Server closing')
        s.close()
        break
    except KeyboardInterrupt:
        print('Server closing')
        s.close()
        break
    else:
        print('Connection from', addr)

But the KeyboardInterrupt is never caught because it happens inside the socket.timeout exception handler. This is the output when pressing Ctrl-C

c:\Users\JMatos\MEOCloud\Python>python file_server.py
Server started
Traceback (most recent call last):
  File "file_server.py", line 40, in <module>
    conn, addr = s.accept()
  File "C:\Python35-32\lib\socket.py", line 195, in accept
    fd, addr = self._accept()
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "file_server.py", line 40, in <module>
    conn, addr = s.accept()
KeyboardInterrupt

Is there any way to catch the KeyboardInterrupt exception inside the socket.timeout exception handler?

My env is Windows 7P+SP1 x64, Python 3.5.2 32b.

Thanks in advance,

JM


Solution

  • The problem is not the socket timeout. The problem is where you're expecting the exception to be thrown. Change the code to:

    try:
        while True:
            try:
                conn, addr = s.accept()
            except socket.timeout:
                 pass
            except Exception as exc:
                 print(str(exc))
                 print('Server closing')
                 s.close()
                 break
        else:
            print('Connection from', addr)
    except KeyboardInterrupt:
        print('Server closing')
        s.close()