简体   繁体   English

具有多处理功能的 python 中 IPC 的优雅解决方案

[英]Elegant solution for IPC in python with multiprocessing

I have two independent processes on the same machine in need of IPC.我在需要 IPC 的同一台机器上有两个独立的进程。 As of now, I have this working solution:截至目前,我有这个工作解决方案:

server.py服务器.py

#!/usr/bin/python3
from multiprocessing.managers import BaseManager
from multiprocessing import Process, Queue

def do_whatever():
    print('function do whatever, triggered by xyz')
    # do something

def start_queue_server(q):
    class QueueManager(BaseManager): pass

    QueueManager.register('get_queue', callable=lambda:q)
    m = QueueManager(address=('', 55555), authkey=b'tuktuktuk')
    s = m.get_server()
    s.serve_forever()

def main():
    queue = Queue()
    proc = Process(target=start_queue_server, args=(queue,))  
    proc.start()

    while True:
        command = queue.get()
        print('command from queue:', command)

        if command == 'xyz':
            do_whatever()

        # many more if, elif, else statements

if __name__ == "__main__":
    main()

client.py客户端.py

#!/usr/bin/python3

from multiprocessing.managers import BaseManager

def communicator(command):
    class QueueManager(BaseManager): pass
    QueueManager.register('get_queue')

    m = QueueManager(address=('', 55555), authkey=b'tuktuktuk')
    m.connect()
    queue = m.get_queue()
    queue.put(command)

def main():
    command = ('xyz')
    communicator(command)

if __name__ == "__main__":
    main()
  • Is there a more elegant way to call 'do_whatever' than parsing the commands passed on by the queue and then calling the target function?有没有比解析队列传递的命令然后调用目标 function 更优雅的调用'do_whatever'的方法?
  • Can I somehow pass on a reference to 'do_whatever' and call it directly from the client?我可以以某种方式传递对“do_whatever”的引用并直接从客户端调用它吗?
  • How is an answer from the server, eg True or False, communicated to the client?服务器如何将答案(例如 True 或 False)传达给客户端? I tried passing a shared variable instead of a queue object but failed.我尝试传递共享变量而不是队列 object 但失败了。 Do I need to open another connection using a second socket to pass the answer?我是否需要使用第二个套接字打开另一个连接来传递答案?

I read the python documentation but couldn't find more options for unrelated processes.我阅读了 python 文档,但找不到更多不相关进程的选项。 Inputs would be welcome!欢迎提供意见! Cheers singultus欢呼声

Finally, I settled for an additional Listener最后,我选择了一个额外的 Listener

server.py服务器.py

#!/usr/bin/python3
from multiprocessing.managers import BaseManager
from multiprocessing import Process, Queue
from multiprocessing.connection import Client

def do_whatever():
    print('function do whatever, triggered by xyz')
    # do something

def start_queue_server(q):
    class QueueManager(BaseManager): pass

    QueueManager.register('get_queue', callable=lambda:q)
    m = QueueManager(address=('', 55555), authkey=b'tuktuktuk')
    s = m.get_server()
    s.serve_forever()

def talkback(msg, port):
    conn = Client(address=('', port), authkey=b'tuktuktuk')
    conn.send(msg)
    conn.close()

def main():
    queue = Queue()
    proc = Process(target=start_queue_server, args=(queue,))  
    proc.start()

    while True:
        command = queue.get()
        print('command from queue:', command)

        if command[0] == 'xyz':
            do_whatever()
            talkback('aaa', command[1])

        # many more if, elif, else statements

if __name__ == "__main__":
    main()

client.py客户端.py

#!/usr/bin/python3

from multiprocessing.managers import BaseManager
from multiprocessing.connection import Listener

def communicator(command, talkback=False):
    if talkback:
        listener = Listener(address=('', 0), authkey=b'prusaprinter')
        return_port = listener.address[1]
        command = command + (return_port,)

    class QueueManager(BaseManager): pass
    QueueManager.register('get_queue')

    m = QueueManager(address=('', 55555), authkey=b'tuktuktuk')
    m.connect()
    queue = m.get_queue()
    queue.put(command)

    if talkback:
        conn = listener.accept()
        server_return = conn.recv()
        conn.close()
        listener.close()
        return server_return

def main():
    command = ('xyz')
    communicator(command, True)

if __name__ == "__main__":
    main()

The client opens an available port and starts listening on it.客户端打开一个可用端口并开始监听它。 It then sends the command to the server together with the aforementioned port number.然后它将命令连同上述端口号一起发送到服务器。 The server executes the command, then uses the port number to report back to the client.服务器执行命令,然后使用端口号向客户端报告。 After receiving the answer, the client closes the port.收到应答后,客户端关闭端口。

I have two independent processes on the same machine in need of IPC.我在需要 IPC 的同一台机器上有两个独立的进程。 As of now, I have this working solution:截至目前,我有这个工作解决方案:

server.py服务器.py

#!/usr/bin/python3
from multiprocessing.managers import BaseManager
from multiprocessing import Process, Queue

def do_whatever():
    print('function do whatever, triggered by xyz')
    # do something

def start_queue_server(q):
    class QueueManager(BaseManager): pass

    QueueManager.register('get_queue', callable=lambda:q)
    m = QueueManager(address=('', 55555), authkey=b'tuktuktuk')
    s = m.get_server()
    s.serve_forever()

def main():
    queue = Queue()
    proc = Process(target=start_queue_server, args=(queue,))  
    proc.start()

    while True:
        command = queue.get()
        print('command from queue:', command)

        if command == 'xyz':
            do_whatever()

        # many more if, elif, else statements

if __name__ == "__main__":
    main()

client.py客户端.py

#!/usr/bin/python3

from multiprocessing.managers import BaseManager

def communicator(command):
    class QueueManager(BaseManager): pass
    QueueManager.register('get_queue')

    m = QueueManager(address=('', 55555), authkey=b'tuktuktuk')
    m.connect()
    queue = m.get_queue()
    queue.put(command)

def main():
    command = ('xyz')
    communicator(command)

if __name__ == "__main__":
    main()
  • Is there a more elegant way to call 'do_whatever' than parsing the commands passed on by the queue and then calling the target function?有没有比解析队列传递的命令然后调用目标 function 更优雅的方法来调用“do_whatever”?
  • Can I somehow pass on a reference to 'do_whatever' and call it directly from the client?我可以以某种方式传递对“do_whatever”的引用并直接从客户端调用它吗?
  • How is an answer from the server, eg True or False, communicated to the client?来自服务器的答案(例如 True 或 False)如何传达给客户端? I tried passing a shared variable instead of a queue object but failed.我尝试传递共享变量而不是队列 object 但失败了。 Do I need to open another connection using a second socket to pass the answer?我是否需要使用第二个套接字打开另一个连接来传递答案?

I read the python documentation but couldn't find more options for unrelated processes.我阅读了 python 文档,但找不到更多不相关进程的选项。 Inputs would be welcome!欢迎输入! Cheers singultus干杯singultus

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM