Как поймать KeyboardInterrupt из обработчика исключений socket.timeout?

Я пытаюсь разработать простой сервер сокетов с неблокирующим приемом (с использованием settimeout), но я хотел бы иметь возможность остановить его с помощью Ctrl-C (KeyboardInterrupt).

Мой код таков:

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)

Но KeyboardInterrupt никогда не перехватывается, потому что это происходит внутри обработчика исключений socket.timeout. Это вывод при нажатии 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

Есть ли способ поймать исключение KeyboardInterrupt внутри обработчика исключений socket.timeout?

Моя среда — Windows 7P+SP1 x64, Python 3.5.2 32b.

Заранее спасибо,

JM


person jmatos    schedule 15.04.2017    source источник


Ответы (1)


Проблема не в тайм-ауте сокета. Проблема в том, что вы ожидаете, что будет выброшено исключение. Измените код на:

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()
person Labrys Knossos    schedule 15.04.2017
comment
Спасибо, так получилось. - person jmatos; 15.04.2017
comment
Отличный ответ спасибо! - person Peter C; 04.05.2021