Python 은 원 격 방법 호출 을 어떻게 실현 합 니까?
sockets,multiprocessing connections 또는 ZeroMQ 와 같은 메시지 전송 층 에서 간단 한 원 격 프로 세 스 호출(RPC)을 실현 하고 싶 습 니 다.
해결 방안
함수 요청,파라미터,반환 값 을 pickle 인 코딩 으로 사용 한 후,서로 다른 해석 기 에서 pickle 바이트 문자열 을 직접 전송 하면 RPC 를 쉽게 실현 할 수 있 습 니 다.다음은 서버 에 통합 할 수 있 는 간단 한 PRC 프로세서 입 니 다.
# rpcserver.py
import pickle
class RPCHandler:
def __init__(self):
self._functions = { }
def register_function(self, func):
self._functions[func.__name__] = func
def handle_connection(self, connection):
try:
while True:
# Receive a message
func_name, args, kwargs = pickle.loads(connection.recv())
# Run the RPC and send a response
try:
r = self._functions[func_name](*args,**kwargs)
connection.send(pickle.dumps(r))
except Exception as e:
connection.send(pickle.dumps(e))
except EOFError:
pass
이 프로 세 서 를 사용 하려 면 메시지 서버 에 추가 해 야 합 니 다.여러 가지 선택 이 있 지만 멀 티 프로 세 싱 라 이브 러 리 를 사용 하 는 것 이 가장 간단 합 니 다.다음은 RPC 서버 의 예 입 니 다.
from multiprocessing.connection import Listener
from threading import Thread
def rpc_server(handler, address, authkey):
sock = Listener(address, authkey=authkey)
while True:
client = sock.accept()
t = Thread(target=handler.handle_connection, args=(client,))
t.daemon = True
t.start()
# Some remote functions
def add(x, y):
return x + y
def sub(x, y):
return x - y
# Register with a handler
handler = RPCHandler()
handler.register_function(add)
handler.register_function(sub)
# Run the server
rpc_server(handler, ('localhost', 17000), authkey=b'peekaboo')
원 격 클 라 이언 트 에서 서버 에 접근 하기 위해 서 는 요청 을 전송 하 는 RPC 프 록 시 클래스 를 만들어 야 합 니 다.예컨대
import pickle
class RPCProxy:
def __init__(self, connection):
self._connection = connection
def __getattr__(self, name):
def do_rpc(*args, **kwargs):
self._connection.send(pickle.dumps((name, args, kwargs)))
result = pickle.loads(self._connection.recv())
if isinstance(result, Exception):
raise result
return result
return do_rpc
이 프 록 시 클래스 를 사용 하려 면 서버 연결 에 포장 해 야 합 니 다.예 를 들 어:
>>> from multiprocessing.connection import Client
>>> c = Client(('localhost', 17000), authkey=b'peekaboo')
>>> proxy = RPCProxy(c)
>>> proxy.add(2, 3)
5
>>> proxy.sub(2, 3)
-1
>>> proxy.sub([1, 2], 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "rpcserver.py", line 37, in do_rpc
raise result
TypeError: unsupported operand type(s) for -: 'list' and 'int'
>>>
주의해 야 할 것 은 많은 메시지 층(예 를 들 어 multiprocessing)이 이미 pickle 을 사용 하여 데 이 터 를 직렬 화 했다 는 것 이다.그렇다면 pickle.dumps()와 pickle.loads()호출 을 제거 해 야 합 니 다.토론 하 다.
RPCHAndler 와 RPCProxy 의 기본 적 인 사고방식 은 비교적 간단 하 다.클 라 이언 트 가 foo(1,2,z=3)와 같은 원 격 함 수 를 호출 하려 면 프 록 시 클래스 는 함수 이름과 파 라 메 터 를 포함 하 는 원 그룹('foo',(1,2),{'z':3}을 만 듭 니 다.이 원본 그룹 은 pickle 에 의 해 직렬 화 된 후 네트워크 연결 을 통 해 발생 합 니 다.이 단 계 는 RPCProxy 의getattr__() 방법 되 돌아 오 는 dorpc()패키지 닫 기 중 완료.서버 가 수신 한 후 pickle 반 직렬 화 메 시 지 를 통 해 함수 명 을 찾 아 등 록 했 는 지 확인 한 후 해당 함 수 를 실행 합 니 다.실행 결과(또는 이상)가 pickle 에 의 해 직렬 화 된 후 클 라 이언 트 에 게 되 돌려 보 냅 니 다.우리 의 인 스 턴 스 는 multiprocessing 에 의존 하여 통신 해 야 한다.그러나 이런 방식 은 다른 어떤 정보 시스템 에 도 적용 된다.예 를 들 어 ZeroMQ 에서 RPC 를 실습 하려 면 연결 대상 을 적합 한 ZeroMQ 의 socket 대상 으로 바 꾸 기만 하면 된다.
밑바닥 에 pickle 에 의존 해 야 하기 때문에 안전 문 제 는 고려 해 야 한다.따라서 신뢰 하지 않 거나 인증 되 지 않 은 클 라 이언 트 의 RPC 를 영원히 허용 하지 마 십시오.특히 인터넷 에서 온 임의의 기계 의 접근 을 절대 허용 하지 마 세 요.내부 에서 만 사용 할 수 있 고 방화벽 뒤에 있 으 며 외부 에 노출 되 지 마 세 요.
pickle 대신 JSON,XML 또는 다른 인 코딩 형식 으로 메 시 지 를 정렬 하 는 것 을 고려 할 수 있 습 니 다.예 를 들 어 이 컴퓨터 의 인 스 턴 스 는 JSON 인 코딩 방안 으로 쉽게 바 꿀 수 있다.pickle.loads()와 pickle.dumps()를 json.loads()와 json.dumps()로 교체 하면 됩 니 다.
# jsonrpcserver.py
import json
class RPCHandler:
def __init__(self):
self._functions = { }
def register_function(self, func):
self._functions[func.__name__] = func
def handle_connection(self, connection):
try:
while True:
# Receive a message
func_name, args, kwargs = json.loads(connection.recv())
# Run the RPC and send a response
try:
r = self._functions[func_name](*args,**kwargs)
connection.send(json.dumps(r))
except Exception as e:
connection.send(json.dumps(str(e)))
except EOFError:
pass
# jsonrpcclient.py
import json
class RPCProxy:
def __init__(self, connection):
self._connection = connection
def __getattr__(self, name):
def do_rpc(*args, **kwargs):
self._connection.send(json.dumps((name, args, kwargs)))
result = json.loads(self._connection.recv())
return result
return do_rpc
RPC 를 실현 하 는 비교적 복잡 한 문 제 는 이상 을 어떻게 처리 하 느 냐 하 는 것 이다.적어도 방법 에 이상 이 생 겼 을 때 서버 가 무 너 져 서 는 안 된다.따라서 클 라 이언 트 에 게 돌아 온 이상 이 대표 하 는 의 미 는 잘 설계 해 야 한다.pickle 을 사용 하면 이상 대상 인 스 턴 스 는 클 라 이언 트 에서 역 직렬 화 되 고 던 질 수 있 습 니 다.만약 네가 다른 협 의 를 사용한다 면 다른 방법 을 생각해 봐 야 한다.그러나 적어도 응답 에서 이상 문자열 을 되 돌려 야 합 니 다.우 리 는 JSON 의 예 에서 이런 방식 을 사용 했다.이상 은 Python 이 원 격 방법 호출 을 어떻게 실현 하 는 지 에 대한 상세 한 내용 입 니 다.Python 원 격 방법 호출 에 관 한 자 료 는 다른 관련 글 에 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.