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가 적합한 후보가 될 수 있지만 수행하려는 작업에는 너무 부족할 수 있습니다.
Twisted는 LineReceiver(간단한 라인 기반 메시지용) 또는 보다 우아한 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
'programing' 카테고리의 다른 글
Angular Resources Service를 통한 JSON 읽기 (0) | 2023.10.27 |
---|---|
ORA-22275 오류: 잘못된 LOB 로케이터가 지정되었습니다. (0) | 2023.10.27 |
docker- compose mysql 컨테이너에서 워드프레스 컨테이너에 대한 액세스를 거부함 (0) | 2023.10.27 |
phpMyAdmin에서 저장 프로시저를 작성하는 방법은? (0) | 2023.10.22 |
UIScrollView에서 스크롤을 프로그래밍 방식으로 강제 중지하려면 어떻게 해야 합니까? (0) | 2023.10.22 |