119 votes

Communication interprocessus en Python

Quel est le meilleur moyen de communiquer entre deux exécutions Python distinctes ? Les choses que j'ai essayées :

  • lecture/écriture sur des tuyaux nommés, par exemple os.mkfifo (c'est un peu comme si c'était un jeu d'enfant)
  • dbus services (fonctionnait sur le bureau, mais trop lourd pour le headless)
  • sockets (semble trop bas niveau ; il y a sûrement un module de plus haut niveau à utiliser)

Mon exigence de base est de pouvoir exécuter python listen.py comme un démon, capable de recevoir des messages de la part de python client.py . Le client doit simplement envoyer un message au processus existant et se terminer, avec le code de retour 0 en cas de succès et non nulle en cas d'échec (c'est-à-dire qu'une communication bidirectionnelle sera nécessaire).

182voto

vsekhar Points 1065

En multiprocessing bibliothèque fournit auditeurs et clients qui enveloppent les sockets et vous permettent de passer des objets python arbitraires.

Votre serveur pourrait écouter pour recevoir des objets python :

from multiprocessing.connection import Listener

address = ('localhost', 6000)     # family is deduced to be 'AF_INET'
listener = Listener(address, authkey=b'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()

Votre client peut envoyer des commandes sous forme d'objets :

from multiprocessing.connection import Client

address = ('localhost', 6000)
conn = Client(address, authkey=b'secret password')
conn.send('close')
# can also send arbitrary objects:
# conn.send(['a', 2.5, None, int, sum])
conn.close()

58voto

zeekay Points 22640

Nah, zeromq est la voie à suivre. Délicieux, n'est-ce pas ?

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')

28voto

Basj Points 776

Basé sur la réponse de @vsekhar, voici une version Python 3 avec plus de détails et des connexions multiples :

Serveur

from multiprocessing.connection import Listener

listener = Listener(('localhost', 6000), authkey=b'secret password')
running = True
while running:
    conn = listener.accept()
    print('connection accepted from', listener.last_accepted)
    while True:
        msg = conn.recv()
        print(msg)
        if msg == 'close connection':
            conn.close()
            break
        if msg == 'close server':
            conn.close()
            running = False
            break
listener.close()

Client

from multiprocessing.connection import Client
import time

# Client 1
conn = Client(('localhost', 6000), authkey=b'secret password')
conn.send('foo')
time.sleep(1)
conn.send('close connection')
conn.close()

time.sleep(1)

# Client 2
conn = Client(('localhost', 6000), authkey=b'secret password')
conn.send('bar')
conn.send('close server')
conn.close()

26voto

shx2 Points 14025

D'après mon expérience, rpyc est de loin la manière la plus simple et la plus élégante de procéder.

6voto

GaretJax Points 3345

J'utiliserais des sockets ; la communication locale a été fortement optimisée, de sorte que vous ne devriez pas avoir de problèmes de performance et cela vous donne la possibilité de distribuer votre application sur différents nœuds physiques si le besoin s'en fait sentir.

En ce qui concerne l'approche "de bas niveau", vous avez raison. Mais vous pouvez toujours utiliser un wrapper de plus haut niveau en fonction de vos besoins. XMLRPC pourrait être un bon candidat, mais il est peut-être excessif pour la tâche que vous essayez d'accomplir.

Torsadé offre quelques bonnes implémentations simples du protocole, telles que LineReceiver (pour les messages simples basés sur des lignes) ou le plus élégant AMP (qui était, soit dit en passant, normalisé et mis en œuvre dans différentes langues ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X