multitarea - procesos concurrentes python
comunicación entre procesos en python (6)
Consulte una biblioteca / servidor multiplataforma llamado RabbitMQ. Puede ser demasiado pesado para la comunicación de dos procesos, pero si necesita una comunicación multiproceso o de código múltiple (con varios medios diferentes, por ejemplo, de uno a muchos, colas, etc.), es una buena opción.
Requisitos:
$ pip install pika
$ pip install bson # for sending binary content
$ sudo apt-get rabbitmq-server # ubuntu, see rabbitmq installation instructions for other platforms
Editor (envía datos):
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()
Suscriptor (recibe datos, puede ser múltiple):
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()
Ejemplos basados en https://www.rabbitmq.com/tutorials/tutorial-two-python.html
¿Cuál es una forma limpia y elegante de hacer comunicación entre procesos entre dos procesos Python diferentes? Actualmente uso canalizaciones con nombre en el sistema operativo, pero se siente un poco hacky. Reescribí mis cosas con los servicios dbus
, lo que funcionó, pero parece que al ejecutar el código de forma remota a través de una sesión SSH ahora intenta inicializar X11, lo que parece completamente innecesario para las cosas que quiero hacer (no están relacionadas con la GUI). Entonces quizás dbus
sea un poco pesado. Estaba a punto de rediseñar usando sockets, pero parece bastante bajo, así que pensé que podría haber un módulo de nivel superior que pudiera importar y usar del que simplemente no sé el nombre, y pensé que debería preguntarle SO primero..
Mi requisito es poder ejecutar python foo.py
y hacer que ese proceso lo haga, como un daemon, y poder enviar mensajes con python foo.py --bar
. La última llamada debería simplemente enviar un mensaje al proceso existente y terminar, posiblemente con un código de retorno 0
para el éxito u otro para la falla (por lo que se requerirá alguna comunicación bidireccional).
Desde mi experiencia, rpyc
es, de lejos, la manera más simple y elegante de hacerlo.
(Sé que esta es una vieja pregunta, pero acabo de tropezar con ella ..)
La biblioteca de multiprocessing
proporciona oyentes y clientes que envuelven sockets y le permiten pasar objetos arbitrarios de python.
Su servidor podría escuchar recibir objetos de 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()
Su cliente podría enviar comandos como objetos:
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()
Nah, zeromq es el camino a seguir. Delicioso, ¿verdad?
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'')
Yo usaría enchufes, pero usaría Twisted para darle algo de abstracción y facilitar las cosas. Su ejemplo Simple Echo Client / Server es un buen lugar para comenzar.
Simplemente tendría que combinar los archivos y crear instancias y ejecutar el cliente o servidor dependiendo de los argumentos pasados.
Yo usaría enchufes; La comunicación local se optimizó en gran medida, por lo que no debería tener problemas de rendimiento y le da la capacidad de distribuir su aplicación a diferentes nodos físicos si surgieran las necesidades.
Con respecto al enfoque de "bajo nivel", tienes razón. Pero siempre puedes usar un contenedor de nivel superior dependiendo de tus necesidades. XMLRPC podría ser un buen candidato, pero tal vez sea excesivo para la tarea que intenta realizar.
Twisted ofrece algunas buenas implementaciones simples de protocolo, como LineReceiver (para mensajes simples basados en líneas) o el más elegante AMP (que, por cierto, estaba estandarizado e implementado en diferentes idiomas ).