套接字上的select()和另一个事件机制

时间:2016-02-17 09:42:31

标签: python sockets select message-queue

我希望在数据可用时从套接字读取,并且在同一个线程中我想从消息队列中读取项目,如下所示:

while True:
    ready = select.select([some_socket, some_messagequeue], [], [])[0]
    if some_socket in ready:
        read_and_handle_data_from_socket()
    if some_messagequeue in ready:
        read_and_handle_data_from_messagequeue()

换句话说:一旦线程通过某个进程内部消息传递系统接收消息,我想中止select()

从我现在读到的内容中我发现了两种方法:select在消息队列本身上,或创建os.pipe()以便中止select(),但我找不到一个好的方法实施。

方法1 :似乎有两个Queue实现:multiprocessing.Queuequeue.Queue(Python3)。虽然multiprocessing.Queue有一个_reader成员可以与select()一起使用,但只有queue.Queue允许任意数据结构排队,而不必捣乱。

问题:还有办法在select()上使用queue.Queue吗?

方法2 :看起来像这样:

import os, queue, select
r, w = os.pipe()
some_socket = 67  # FD to some other socket
q = queue.Queue()
def read_fd():
    while True:
        ready = select.select([r, some_socket], [], [])[0]
        if r in ready:
            os.read(r, 100)
            print('handle task: ', q.get())
        if some_socket in ready:
            print('socket has data')

threading.Thread(target=read_fd, daemon=True).start()
while True:
    q.put('some task')
    os.write(w, b'x')
    print('scheduled task')
    time.sleep(1)

这是有效的 - 但在我看来,这段代码非常繁琐而且不是非常pythonic。 问题有没有更好的方式通过os.pipe(或任何其他实施方式)发送'信号'?

方法3..N 问题:您如何解决这个问题?

我知道像ZeroMQ这样的库但是因为我正在开发一个嵌入式项目,所以我更喜欢本机Python(3.3)发行版附带的解决方案。我认为应该有一个像第一个例子一样简短的解决方案 - 毕竟我只想中止 select()如果消息队列上发生了某些事情。

2 个答案:

答案 0 :(得分:0)

方法3:有两个主题。 1等待选择。 2等待消息队列。 Mutex防止它们同时发射。如果您不打算使用它们,为什么要有线程?

答案 1 :(得分:0)

您可以创建pipe对文件描述符,通过写入其写入端来发送信号队列,并在读取端的同一select中等待队列活动。管道。

在Linux上,还有 eventfd(2)系统调用,可以将用于同一目的。而不是pipe(2)({ {3}}我可能会有用。)