programing

Python에서의 프로세스간 통신

newsource 2023. 10. 27. 21:57

Python에서의 프로세스간 통신

두 개의 서로 다른 파이썬 실행 시간 사이에 통신하는 좋은 방법은 무엇입니까?시도한 일:

  • 이름 있는 파이프에 읽기/쓰기(예: feels 해킹
  • services(데스크톱에서는 worked이지만 헤드리스를 사용하기에는 무게가 너무 무겁습니다.
  • 소켓(seems가 너무 낮아서 사용할 수 있는 모듈이 있나요?)

내 기본 요구사항은 실행할 수 있는 것입니다.python listen.py데몬처럼, 메시지를 받을 수 있습니다.python client.py. 클라이언트는 기존 프로세스에 메시지를 보내고 반환 코드와 함께 종료해야 합니다.0성공의 경우 0이 아닌 경우(즉, 양방향 통신이 필요합니다).

라이브러리는 소켓을 랩핑하는 리스너와 클라이언트를 제공하며 임의의 파이썬 객체를 전달할 수 있게 해줍니다.

서버에서 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()

클라이언트가 개체로 명령을 보낼 수 있습니다.

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

아니요, 제로맥이 가야 할 길입니다.맛있죠?

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

@vsekhar의 답변을 바탕으로, 더 자세한 내용과 여러 연결이 포함된 Python 3 버전을 소개합니다.

서버

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

고객

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

내 경험으로는, 그것을 실행하는 가장 단순하고 우아한 방법입니다.

저는 소켓을 사용합니다. 로컬 통신은 강력하게 최적화되었기 때문에 성능 문제가 발생하지 않아야 하며, 필요한 경우 애플리케이션을 다른 물리적 노드에 배포할 수 있는 기능을 제공합니다.

"저수준" 접근법에 관해서는, 당신이 맞습니다.하지만 필요에 따라 항상 높은 수준의 포장지를 사용할 수 있습니다.XMLRPC가 적합한 후보가 될 수 있지만 수행하려는 작업에는 너무 부족할 수 있습니다.

TwistedLineReceiver(간단한 라인 기반 메시지용) 또는 보다 우아한 AMP(참고로 표준화되어 다른 언어로 구현된)와 같은 몇 가지 훌륭한 프로토콜 간단한 구현을 제공합니다.

RabbitMQ라고 불리는 크로스 플랫폼 라이브러리/서버를 확인해 보십시오. 2-프로세스 통신에는 너무 무거울 수 있지만, 다중 프로세스 또는 다중 코드베이스 통신이 필요한 경우(예를 들어, 일대일, 대기열 등 다양한 수단을 사용하는) 좋은 옵션입니다.

요구사항:

$ 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 을 기반으로 한 예제

소켓을 사용하고 싶지만 Twisted를 사용하여 추상화를 제공하고 쉽게 작업할 수 있습니다.간단한 에코 클라이언트/서버 예제는 시작하기 좋은 방법입니다.

전달된 인수에 따라 파일을 결합하고 클라이언트 또는 서버를 인스턴스화하여 실행하기만 하면 됩니다.

Python IPC의 첫 번째 결과 중 하나로 이 스레드를 찾았지만 Async로 실행할 수 있는 것을 찾고 있었습니다.IO. 결국 좋은 비동기 기능을 제공하는 IPyC를 발견하고 그 보석을 공유하기 위해 돌아왔습니다.IPyC는 동기화 구현도 지원합니다.

두 개의 다른 프로세스에서 IPyC 라이브러리를 사용할 수 있지만, 여기 같은 파일에 두 개의 비동기 작업이 있는 작은 예가 있습니다.TCP:9999를 기본 포트로 사용하고 있습니다.

참고: 이 예제는 다음과 충돌합니다.unexpected keyword argument 'loop'Python >=3.10에서, 이는 비동기의 인터페이스 변경으로 인한 것입니다.v3.9로 테스트를 해봤습니다.

import asyncio
import ipyc
import json
import logging
logging.basicConfig(level=logging.INFO)  # Set to DEBUG to see inner workings

# IPyC has support for custom (de)serialization; using json as example here
ipyc.IPyCSerialization.add_custom_serialization(list, json.dumps)
ipyc.IPyCSerialization.add_custom_deserialization(list, json.loads)


## Host stuff
host = ipyc.AsyncIPyCHost()

@host.on_connect
async def on_client_connect(connection: ipyc.AsyncIPyCLink):
    logging.info("Got a connection")
    while connection.is_active():
        message = await connection.receive()
        if message:
            logging.info(f"Received: {message}")
    logging.info("Connection closed")

## Client stuff
async def client_task():
    client = ipyc.AsyncIPyCClient()

    link = await client.connect()

    for i in range(3):
        await link.send(["Hello World!", i, 3.14])
        await asyncio.sleep(1)

    await client.close()  # Close the connection
    await asyncio.sleep(1)

## AsyncIO stuff
loop = asyncio.get_event_loop()
loop.create_task(host.start())
loop.run_until_complete(client_task())

언급URL : https://stackoverflow.com/questions/6920858/interprocess-communication-in-python