Python 非阻塞多处理.connection.Listener?

Python 非阻塞多处理.connection.Listener?,python,sockets,asynchronous,python-3.3,python-multiprocessing,Python,Sockets,Asynchronous,Python 3.3,Python Multiprocessing,我使用multiprocessing.connection.Listener在进程之间进行通信,这对我来说很有吸引力。现在,我非常希望我的mainloop在来自客户端的命令之间执行其他操作。不幸的是,listener.accept()会阻止执行,直到从客户端进程建立连接为止 是否有一种简单的方法来管理multiprocessing.connection的非阻塞检查?暂停?或者我应该使用专用线程 # Simplified code: from multiprocessing.co

我使用multiprocessing.connection.Listener在进程之间进行通信,这对我来说很有吸引力。现在,我非常希望我的mainloop在来自客户端的命令之间执行其他操作。不幸的是,listener.accept()会阻止执行,直到从客户端进程建立连接为止

是否有一种简单的方法来管理multiprocessing.connection的非阻塞检查?暂停?或者我应该使用专用线程

    # Simplified code:

    from multiprocessing.connection import Listener

    def mainloop():
        listener = Listener(address=(localhost, 6000), authkey=b'secret')

        while True:
            conn = listener.accept() # <---  This blocks!
            msg = conn.recv() 
            print ('got message: %r' % msg)
            conn.close()
#简化代码:
从multiprocessing.connection导入侦听器
def mainloop():
listener=listener(地址=(localhost,6000),authkey=b'secret')
尽管如此:

conn=listener.accept()#我自己没有使用listener对象-对于此任务,我通常使用
多处理.Queue
;doco位于以下链接:

该对象可用于在Python进程之间发送和接收任何可pickle的对象,并具有良好的API;我想你最感兴趣的是:

  • 进行中
    • .put('some message')
  • 在过程B中
    • .get_nowait()#将引发队列。如果没有可用的,则为空-处理该队列以继续执行
唯一的限制是,您需要在某个时刻控制这两个流程对象,以便能够将队列分配给它们—类似于这样:

import time
from Queue import Empty
from multiprocessing import Queue, Process


def receiver(q):
    while 1:
        try:
            message = q.get_nowait()
            print 'receiver got', message
        except Empty:
            print 'nothing to receive, sleeping'
            time.sleep(1)


def sender(q):
    while 1:
        message = 'some message'
        q.put('some message')
        print 'sender sent', message
        time.sleep(1)


some_queue = Queue()

process_a = Process(
    target=receiver,
    args=(some_queue,)
)

process_b = Process(
    target=sender,
    args=(some_queue,)
)

process_a.start()
process_b.start()

print 'ctrl + c to exit'
try:
    while 1:
        time.sleep(1)
except KeyboardInterrupt:
    pass

process_a.terminate()
process_b.terminate()

process_a.join()
process_b.join()
队列很好,因为您实际上可以为完全相同的队列对象拥有任意多的使用者和生产者(便于分发任务)


我应该指出,仅仅在进程上调用
.terminate()
是一种糟糕的形式-您应该使用全新的消息传递系统来传递关机消息或类似性质的消息。

多处理模块附带了一个很好的功能,称为Pipe()。这是一种在两个进程之间共享资源的好方法(以前从未尝试过两个以上)。随着Python3.80的出现,多处理模块中出现了共享内存功能,但我还没有真正测试过它,因此我无法对此进行担保 您将使用类似以下内容的管道函数

from multiprocessing import Pipe

.....

def sending(conn):
    message = 'some message'
    #perform some code
    conn.send(message)
    conn.close()

receiver, sender = Pipe()
p = Process(target=sending, args=(sender,))
p.start()
print receiver.recv()   # prints "some message"
p.join()
这样,当您需要一个进程的输入时,您应该能够让单独的进程独立运行。如果由于另一个进程的未释放数据而导致错误,您可以将其置于睡眠状态或暂停状态,或者在另一个进程完成该任务并将其发送过来时,使用while循环不断检查挂起状态

while not parent_conn.recv():
    time.sleep(5)

这将使它处于无限循环中,直到另一个进程完成运行并发送结果。这也比排队快2-3倍。虽然队列也是一个不错的选择,但我个人不使用它。

您可以在线程中运行阻塞功能:

conn = await loop.run_in_executor(None, listener.accept)
我发现的一个解决方案(虽然可能不是最“优雅”的解决方案)是使用
conn.poll
()如果侦听器有新数据,poll将返回
True
,并且(最重要的是)如果没有参数传递给它,则是非阻塞的。我不能100%确定这是最好的方法,但我只成功地运行了一次
listener.accept()
,然后使用以下语法重复获取输入(如果有可用的话)

来自multiprocessing.connection导入侦听器的

def mainloop():
运行=真
listener=listener(地址=(localhost,6000),authkey=b'secret')
conn=listener.accept()
msg=“”
运行时:
而conn.poll()
msg=conn.recv()
打印(f“获取消息:{msg}”)
如果消息==“退出”:
运行=错误
#其他代码可以转到这里
打印(f“我也可以运行!上次收到的消息是{msg}”)
康涅狄格州关闭

如果您一次最多只想获取一条消息,则条件语句中的“while”可以替换为“if”。请谨慎使用,因为它似乎有点“hacky”,而且我在其他地方没有找到为此目的使用
conn.poll

详细说明“您需要控制两个进程对象”,如果这是为了允许两个进程在不同的时间启动,或者可能存在于不同的服务器上,那么我恐怕我的建议是无用的-我想你需要一个线程或什么的,为此我通常使用gRPC。你试过并测试过它吗?现在它可靠吗?