asyncioとwebsocketsとPython 3.5.2を使用して、基本WebSocketクライアントを実装しようとしています。asyncioとwebsocketコールバックを非同期にする
基本的には、connect_to_dealer
をブロッキングコールにしたいが、別のスレッドでwebsocketメッセージを待つ。
いくつかのドキュメントを読んだあと(私はPythonにはほとんど経験がありません)、私はasyncio.ensure_future()
がコルーチン(listen_for_message
)を渡すことが道だと結論づけました。
は今、私は別のスレッドでlisten_for_message
を実行するために取得するが、コルーチンの中から、私は通話同期を作るためにawait
または任意の他のメカニズムを使用するように見えることはできません。私がそれをすると、実行は単純な場合でも、永遠に(ハングする)待つ。sleep
。
私が間違っていることを知りたいのですが。
async def listen_for_message(self, future, websocket):
while (True):
try:
await asyncio.sleep(1) # It hangs here
print('Listening for a message...')
message = await websocket.recv() # If I remove the sleep, hangs here
print("< {}".format(message))
future.set_result(message)
future.done()
except websockets.ConnectionClosed as cc:
print('Connection closed')
except Exception as e:
print('Something happened')
def handle_connect_message(self, future):
# We must first remove the websocket-specific payload because we're only interested in the connect protocol msg
print(future.result)
async def connect_to_dealer(self):
print('connect to dealer')
websocket = await websockets.connect('wss://mywebsocket'))
hello_message = await websocket.recv()
print("< {}".format(hello_message))
# We need to parse the connection ID out of the message
connection_id = hello_message['connectionId']
print('Got connection id {}'.format(connection_id))
sub_response = requests.put('https://subscribetotraffic{user_id}?connection={connection_id}'.format(user_id='username', connection_id=connection_id), headers=headers)
if sub_response.status_code == 200:
print('Now we\'re observing traffic')
else:
print('Oops request failed with {code}'.format(code=sub_response.status_code))
# Now we need to handle messages but continue with the regular execution
try:
future = asyncio.get_event_loop().create_future()
future.add_done_callback(self.handle_connect_message)
asyncio.ensure_future(self.listen_for_message(future, websocket))
except Exception as e:
print(e)
shongoloこんにちは、私は明示的な先物で作業する必要はありませんでしたが、私はそれを読みますドキュメントに書いて、それを使っただけです。 私はあなたの提案のおかげで私の問題を解決しました、私はキーが 'connect_to_dealer()'コルーチン内から 'asyncio.ensure_future(listen_for_message(websocket))'を呼び出さないことだと思います。 – mdelolmo
それは喜んで解決策を引き起こしました。 'loop.run_until_complete()'を使って全てのコルーチンを動かす必要があり、必要ならば(例えばタスクを使って) 'loop.run_forever()'を使ってコード内のどこかで 'ensure_future()'を呼び出すことはOKです。 – shongololo