Подтвердить что ты не робот

Межпроцессное взаимодействие в Python

Что такое чистый и элегантный способ межпроцессного взаимодействия между двумя различными процессами python? В настоящее время я использую именованные каналы в ОС, но он немного взломан. Я переписал свой материал с dbus службами, которые работали, но, похоже, при запуске кода удаленно через сеанс SSH он теперь пытается инициализировать X11, который кажется совершенно ненужным для вещей, которые я хочу сделать (они не связаны с графическим интерфейсом), Так что, может быть, dbus слишком тяжело. Я собирался снова перепроектировать, используя сокеты, но он выглядит довольно низкоуровневым, поэтому я подумал, что может быть модуль более высокого уровня, который я мог бы импортировать и использовать, который я просто не знаю имени, и я подумал, что я должен спросить о SO первый..

Мое требование состоит в том, чтобы иметь возможность запускать python foo.py и иметь этот процесс, просто делающий это, как демон, и иметь возможность отправлять ему сообщения с помощью python foo.py --bar. Последний вызов должен просто отправить сообщение в существующий процесс и завершиться, возможно, с кодом возврата 0 для успеха или другого для отказа (так что потребуется некоторая двусторонняя связь).

4b9b3361

Ответ 1

Библиотека 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()

Ответ 2

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

Ответ 3

По моему опыту rpyc - это самый простой и изящный способ сделать это.

(Я знаю, что это старый вопрос, но я только что наткнулся на него.)

Ответ 4

Я бы использовал сокеты; локальная связь была сильно оптимизирована, поэтому у вас не должно быть проблем с производительностью, и это дает вам возможность распространять ваше приложение на разные физические узлы, если это необходимо.

Что касается "низкоуровневого" подхода, вы правы. Но вы всегда можете использовать обертку более высокого уровня в зависимости от ваших потребностей. XMLRPC может быть хорошим кандидатом, но, возможно, это слишком сложно для задачи, которую вы пытаетесь выполнить.

Twisted предлагает некоторые хорошие простые простые протоколы, такие как LineReceiver (для простых текстовых сообщений) или более элегантный AMP (который, кстати, был стандартизован и реализован на разных языках).

Ответ 5

Я бы использовал сокеты, но использовал Twisted, чтобы дать вам некоторую абстракцию и сделать все просто. Их простой пример Echo Client/Server - это хорошее место для начала.

Вам просто нужно объединить файлы и создать экземпляр и запустить клиент или сервер в зависимости от переданных аргументов.

Ответ 6

Проверьте кросс-платформенную библиотеку/сервер под названием RabbitMQ. Может быть слишком тяжелым для двухпроцессорной связи, но если вам нужна многопроцессорная или многокодовая база данных (с различными различными способами, например, один-ко-многим, очереди и т.д.), Это хороший вариант.

Требования:

$ 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