Python中的进程间通信
什么是在两个不同的python进程之间进行进程间通信的干净优雅的方式? 我目前在操作系统中使用命名pipe道,但感觉有点哈克。 我重写了我的东西与dbus
服务,它的工作,但似乎通过SSH会话远程运行的代码,现在试图初始化X11这似乎完全不必要的事情,我想要做的事情(他们不是GUI相关)。 所以也许dbus
有点太重了。 我正要重新devise使用套接字,但它似乎很低层次,所以我认为可能有一个更高级别的模块,我可以导入和使用,我根本不知道名称,我想我应该问的SO第一..
我的要求是能够运行python foo.py
并让该进程像守护进程一样执行它,并能够使用python foo.py --bar
发送消息。 后者调用应该只是发送一个消息到现有的进程并终止,可能返回代码0
成功或其他失败(所以一些双向通信将被要求)。
那么, zeromq是要走的路。 美味,不是吗?
import argparse import zmq parser = argparse.ArgumentParser(description='zeromq server/client') parser.add_argument('--bar') args = parser.parse_args() if args.bar: # client context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect('tcp://127.0.0.1:5555') socket.send(args.bar) msg = socket.recv() print msg else: # server context = zmq.Context() socket = context.socket(zmq.REP) socket.bind('tcp://127.0.0.1:5555') while True: msg = socket.recv() if msg == 'zeromq': socket.send('ah ha!') else: socket.send('...nah')
multiprocessing
库提供包装套接字的侦听器和客户端 ,并允许您传递任意的python对象。
你的服务器可以听取python对象:
from multiprocessing.connection import Listener address = ('localhost', 6000) # family is deduced to be 'AF_INET' listener = Listener(address, authkey='secret password') conn = listener.accept() print 'connection accepted from', listener.last_accepted while True: msg = conn.recv() # do something with msg if msg == 'close': conn.close() break listener.close()
你的客户端可以发送命令作为对象:
from multiprocessing.connection import Client address = ('localhost', 6000) conn = Client(address, authkey='secret password') conn.send('close') # can also send arbitrary objects: # conn.send(['a', 2.5, None, int, sum]) conn.close()
从我的经验来看, rpyc
是迄今为止最简单,最优雅的方法。
(我知道这是一个古老的问题,但我只是偶然发现了它。)
我会使用套接字; 本地通信得到了极大的优化,所以您不应该遇到性能问题,并且在需要的时候,您可以将应用程序分发到不同的物理节点。
关于“低级”方法,你是对的。 但是,您可以随时根据需要使用更高级别的包装。 XMLRPC可能是一个很好的候选人,但它可能是你想要执行的任务矫枉过正。
Twisted提供了一些很好的协议简单的实现,例如LineReceiver (用于简单的基于行的消息)或更优雅的AMP(顺便说一句, 用不同的语言标准化和实现 )。
我会使用套接字,但使用Twisted给你一些抽象,并使事情变得容易。 他们的Simple Echo Client / Server例子是一个很好的开始。
你只需要结合这些文件并根据传递的参数实例化并运行客户端或服务器。
查看一个名为RabbitMQ的跨平台库/服务器。 双进程通信可能太重了,但是如果你需要多进程或多代码库通信(用各种不同的方式,例如一对多,队列等),这是一个不错的select。
要求:
$ pip install pika $ pip install bson # for sending binary content $ sudo apt-get rabbitmq-server # ubuntu, see rabbitmq installation instructions for other platforms
发布者(发送数据):
import pika, time, bson, os connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() channel.exchange_declare(exchange='logs', type='fanout') i = 0 while True: data = {'msg': 'Hello %s' % i, b'data': os.urandom(2), 'some': bytes(bytearray(b'\x00\x0F\x98\x24'))} channel.basic_publish(exchange='logs', routing_key='', body=bson.dumps(data)) print("Sent", data) i = i + 1 time.sleep(1) connection.close()
订户(接收数据,可以是多个):
import pika, bson connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) channel = connection.channel() channel.exchange_declare(exchange='logs', type='fanout') result = channel.queue_declare(exclusive=True) queue_name = result.method.queue channel.queue_bind(exchange='logs', queue=queue_name) def callback(ch, method, properties, body): data = bson.loads(body) print("Received", data) channel.basic_consume(callback, queue=queue_name, no_ack=True) channel.start_consuming()
基于https://www.rabbitmq.com/tutorials/tutorial-two-python.html的示例;