ZMQ 套接字在 Python 中优雅地终止

boa*_*ter 6 python sockets signals zeromq

我有以下 ZMQ 脚本

#!/usr/bin/env python2.6


import signal
import sys
import zmq


context = zmq.Context()
socket = context.socket(zmq.SUB)

def signal_term_handler(signal, fname):
    socket.close()
    sys.exit(0)

def main():
    signal.signal(signal.SIGTERM, signal_term_handler)

    socket.connect('tcp://16.160.163.27:8888')
    socket.setsockopt(zmq.SUBSCRIBE, '')
    print 'Waiting for a message'

    while True:
        (event, params) = socket.recv().split()
        # ... doing something with that data ...

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

当 I 时Ctrl-C,我收到以下错误:

Traceback (most recent call last):
  File "./nag.py", line 28, in <module>
    main()
  File "./nag.py", line 24, in main
    (event, params) = socket.recv().split()
  File "socket.pyx", line 628, in zmq.backend.cython.socket.Socket.recv (zmq/backend/cython/socket.c:5616)
  File "socket.pyx", line 662, in zmq.backend.cython.socket.Socket.recv (zmq/backend/cython/socket.c:5436)
  File "socket.pyx", line 139, in zmq.backend.cython.socket._recv_copy (zmq/backend/cython/socket.c:1771)
  File "checkrc.pxd", line 11, in zmq.backend.cython.checkrc._check_rc (zmq/backend/cython/socket.c:5863)
KeyboardInterrupt
Run Code Online (Sandbox Code Playgroud)

现在,我以为我处理了套接字的关闭,当从用户那里接收到终止信号时,很好,那么为什么我会收到这些丑陋的消息。我错过了什么。

请注意,我在 Google 和 StackOverflow 上进行了一些搜索,但没有找到任何可以解决此问题的方法。

谢谢。

编辑对于已经走到这一步的任何人——user3666197提出了一种非常好的和健壮的方法来处理执行过程中的终止或任何异常。

use*_*197 7

事件处理方式

虽然演示代码很小,但现实世界的系统,多主机/多进程通信系统,通常应在其主控制循环中处理所有不利影响的事件。

try:
    context = zmq.Context()         # setup central Context instance
    socket  = ...                   # instantiate/configure all messaging archetypes
    # main control-loop ----------- # ----------------------------------------
    #
    # your app goes here, incl. all nested event-handling & failure-resilience
    # ----------------------------- # ----------------------------------------
except ...:
    #                               # handle IOErrors, context-raised exceptions
except Keyboard Interrupt:
    #                               # handle UI-SIG
except:
    #                               # handle other, exceptions "un-handled" above
finally:
    #                               # GRACEFULL TERMINATION
    # .setsockopt( zmq.LINGER, 0 )  #           to avoid hanging infinitely
    # .close()                      # .close()  for all sockets & devices
    #
    context.term()                  #           Terminate Context before exit
Run Code Online (Sandbox Code Playgroud)