Python:Queue.get()阻止代码检查套接字连接

时间:2011-03-09 22:07:52

标签: python sockets queue

我正在运行一个线程,该线程从队列中获取消息,将其发送到客户端,并接收确认。如果客户端断开连接,则线程捕获套接字错误并终止。问题是如果msgQ为空,则线程永远不会检查套接字连接。有没有办法设置此代码,所以即使队列为空,检查套接字? (问题是,没有消息,没有什么可以发送)

我是否需要发送一个特殊的ping?pong!消息如果msgQ为空(并在客户端检查消息是日志数据还是ping?)?任何帮助,将不胜感激。

def run(self): 
    while not self._terminate: 
        try: 
            msgs = self.msgQ.get()

            self.sock.send(pickle.dumps(msgs))
            rdy = pickle.loads(self.sock.recv(2097152))
        except socket.error, EOFError: 
            print 'log socketmanager closing'
            self.terminate()
            break
        except Empty: pass

3 个答案:

答案 0 :(得分:1)

如果msgQ为空,则对self.msgQ.get()的调用会引发Empty例外,并完全跳过对self.sock.send()self.sock.recv()的调用。 Empty例外的异常处理程序不执行任何操作,因此您的代码将busy wait,直到msgQ显示某些内容而没有调用sendrecv

一种可能的解决方案是使用python select module检查异常处理程序中的套接字。这些方面的东西:

def run(self): 
    while not self._terminate: 
        try: 
            msgs = self.msgQ.get()

            self.sock.send(pickle.dumps(msgs))
            rdy = pickle.loads(self.sock.recv(2097152))
        except socket.error, EOFError: 
            print 'log socketmanager closing'
            self.terminate()
            break
        except Empty:
            results = select.select([], [], [self.sock], 0.5) # timeout of 0.5 seconds
            if self.sock in results[2]:
                print 'exceptional condition on socket'
                self.terminate()
                break

答案 1 :(得分:0)

如果您使用的是Queue.Queue,则可以使用可选的blocktimeout args致电Queue.get(),或致电Queue.get_nowait(),其等效于{{1}如果队列为空,将立即返回:

Queue.get(block=False)

答案 2 :(得分:0)

我有一个将Queue和Pipe包装到类中的想法。然后使用select模块检查套接字和管道,不会使用轮询来监视事件。

以下用于包装队列和管道的示例代码:

class MyQueue(object):
"""docstring for MyQueue"""
def __init__(self, arg):
    super(MyQueue, self).__init__()
    # self.arg = arg
    self._queue = Queue.Queue()
    self._rdfd, self._wrfd = os.pipe()
    return

def enQ(self, item=None, block=True, timeout=None):
    os.write(self._wrfd, '+')
    self._queue.put(item)
    return

def deQ(self, block=True, timeout=None):
    _itm = self._queue.get(block=block, timeout=timeout)
    _msg = os.read(self._rdfd, 1)
    return _itm

def get_notify(self):
    return self._rdfd
    print 'append queue'
    self.inp.append(self._myq.get_notify())
    print 'append socket'
    self.inp.append(self.sock)
    print self.inp

    _slp = self.slp
    _inp = self.inp
    _out = self.out
    _err = self.err
    _in, _out, _err = select.select(_inp, _out, _err, _slp)