2015-01-18 3 views
1

python3에서 asyncio를 배우기 위해 간단한 RPC 서버와 클라이언트를 작성했지만 asyncio.run_until_complete로 테스트하면 미래가 이미 설정된 후에 차단됩니다. 코드는 다음과 같습니다. 메인 부분을 확인하십시오. 8asyncio.run_until_complete block after future is

를 : 나는이 프로그램을 실행할 때, 제대로

미래의 결과처럼 data_received에 결과를 표시, 5 + 을 3 CALC하는 기능 파이썬 3.4.2

import asyncio 
import struct 

_req_struct = struct.Struct('<4i') 
_req_size = _req_struct.size 

_resp_struct = struct.Struct('<3i') 
_resp_size = _resp_struct.size 


class SimpleRPCClient(asyncio.Protocol): 
    _transport = None 

    def __init__(self): 
     self._pendings = {} 
     self.seq_id = 0 
     self._cached = bytearray() 

    def connection_made(self, transport): 
     """ 
     First event, create ref to transport 
     """ 
     self._transport = transport 

    def send(self, data): 
     """ 
     proxy to transport.write 
     """ 
     self._transport.write(data) 

    def data_received(self, data): 
     c = self._cached 
     c.extend(data) 
     cursor = 0 
     while len(self._cached) >= (cursor + _resp_size): 
      rid, status, result = _resp_struct.unpack(
       c[cursor:cursor + _resp_size]) 
      if rid in self._pendings: 
       f = self._pendings.pop(rid) 
       f.set_result(result) 
       print("future result: ", f.result()) 

    def calc(self, oprand, op1, op2): 
     rid = self.seq_id 
     self.seq_id += 1 
     future = asyncio.Future() 
     self._pendings[rid] = future 
     self.send(_req_struct.pack(rid, oprand, op1, op2)) 
     return future 


if __name__ == '__main__': 
    loop = asyncio.get_event_loop() 
    host = "127.0.0.1" 
    port = 8087 
    _tr, client = loop.run_until_complete(loop.create_connection(
     SimpleRPCClient, 
     host, 
     port)) 
    f = client.calc(1, 3, 5) 
    loop.run_until_complete(f) 
    print("final result: ", f.result()) 

이다 사용하고 있습니다

그러나 프로그램이 그 이후에 차단되면 최종 결과가 표시되지 않고 미래가 성공적으로 설정되지만 함수가 반환하지 않는 이유는 무엇입니까? 당신이 그것을

import asyncio 
import struct 

_req_struct = struct.Struct('<4i') 
_req_size = _req_struct.size 

_resp_struct = struct.Struct('<3i') 
_resp_size = _resp_struct.size 


class SimpleRPCServer(object): 

    def build_protocol(self): 
     return SimpleRPCConnection() 


class SimpleRPCConnection(asyncio.Protocol): 
    _transport = None 

    def __init__(self): 
     self._cached = bytearray() 

    def connection_made(self, transport): 
     """ 
     First event, create ref to transport 
     """ 
     self._transport = transport 

    def send(self, data): 
     """ 
     proxy to transport.write 
     """ 
     self._transport.write(data) 

    def data_received(self, data): 
     c = self._cached 
     c.extend(data) 
     cursor = 0 
     while len(self._cached) >= (cursor + _req_size): 
      seq_id, oprand, op1, op2 = _req_struct.unpack(
       c[cursor:cursor + _req_size]) 
      self.respond(seq_id, oprand, op1, op2) 
      cursor += _req_size 

     if cursor > len(self._cached): 
      self._cached.clear() 
     else: 
      self._cached[:cursor] = b'' 

    def respond(self, seq_id, oprand, op1, op2): 
     if oprand == 1: 
      self.send(_resp_struct.pack(seq_id, 0, op1 + op2)) 
     elif oprand == 2: 
      self.send(_resp_struct.pack(seq_id, 0, op1 - op2)) 
     elif oprand == 3: 
      self.send(_resp_struct.pack(seq_id, 0, op1 * op2)) 
     elif oprand == 4: 
      try: 
       self.send(_resp_struct.pack(seq_id, 0, op1/op2)) 
      except ZeroDivisionError: 
       self.send(_resp_struct.pack(seq_id, 1, 0)) 
     else: 
      self.send(_resp_struct.pack(seq_id, 0xff, 0)) 

if __name__ == '__main__': 
    loop = asyncio.get_event_loop() 
    server = SimpleRPCServer() 
    loop.run_until_complete(loop.create_server(
     server.build_protocol, 
     "0.0.0.0", 
     8087)) 
    loop.run_forever() 
+0

* 모든 코드를 질문에 넣지 마십시오. 대신에 [* minimal *이지만 완전한 코드 예제를 작성하십시오.] (http://stackoverflow.com/help/mcve) - 질문을 작성할 때 질문에 대답 할 수 있으며 다른 사람들이 문제를 해결하는 데 도움을 줄 수 있습니다. – jfs

답변

0

을 멈추지 않을 당신의 SimpleRPCClient.data_received() 메소드에서 루프를 실행하려는 경우

서버 측

아래에 첨부되어 있습니다.