Receiving streaming data after implementing asyncio websockets as a class?

前端 未结 2 938
粉色の甜心
粉色の甜心 2021-01-07 04:06

My question is closely related to the following question on Stackoverflow and the documentation here. I am defining a websockets-connection as a class. Next, I

相关标签:
2条回答
  • 2021-01-07 04:30

    the problem is in the function

    first loop.run_until_complete run until the future is complete doc run_until_complete
    that mean your function receive will run only one response. run_until_complete is not a callback function!.

    so in your case the main:
    deribit.get_ticks() -> run the future instance __async__get_ticks
    so __async__get_ticks is task: let's see what the task do:
    1.open ws connection:
    2.send request
    3.wait the response of the ws
    4. print(response)
    here the task is done that why you see only one line

       async def __async__get_ticks(self):
          async with self.ws as echo:
             await echo.send(json.dumps(self.request))
             response = await echo.receive()
             print(response)
    

    after explanation: the solution will be simple: need to wrap the line response with while

    async def __async__get_ticks(self):
          async with self.ws as echo:
             await echo.send(json.dumps(self.request))
             while True:
                    response = await echo.receive()
                    print(response)
    
    

    output

    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654476817,"price":7540.54,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654477824,"price":7540.52,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654478831,"price":7540.15,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654479838,"price":7539.83,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654480845,"price":7539.2,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654481852,"price":7538.96,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654482859,"price":7538.9,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654483866,"price":7538.89,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654484873,"price":7538.47,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587654485880,"price":7537.15,"index_name":"btc_usd"}}}
    
    0 讨论(0)
  • 2021-01-07 04:34

    I only worked with Tornado's websockets but they work pretty well and Tornado has many helpers for dealing with async code:

    import json
    import tornado
    from tornado.ioloop import PeriodicCallback
    from tornado.websocket import websocket_connect
    
    
    class EchoWebsocket:
    
        def __init__(self, url, client_id=None, client_secret=None):
            self.url = url
            self.client_id = client_id
            self.client_secret = client_secret
            self.websocket = None
    
        async def connect(self):
            if not self.websocket:
                self.websocket = await websocket_connect(self.url)
    
        async def close(self):
            await self.websocket.close()
            self.websocket = None
    
        async def read(self):
            return await self.websocket.read_message()
    
        async def write(self, message):
            await self.websocket.write_message(message)
    
    
    class DERIBIT:
    
        def __init__(self):
            self.ws = EchoWebsocket(url='wss://test.deribit.com/ws/api/v2')
            self.request = {
                "jsonrpc": "2.0",
                "method": "public/subscribe",
                "id": 42,
                "params": {
                    "channels": ["deribit_price_index.btc_usd"]}
            }
            self.callback = PeriodicCallback(self.get_ticks, 1000)
            self.callback.start()
    
        async def get_ticks(self):
            if not self.ws.websocket:
                await self.ws.connect()
            await self.ws.write(json.dumps(self.request))
            response = await self.ws.read()
            print(response)
    
    
    if __name__ == "__main__":
        deribit = DERIBIT()
        tornado.ioloop.IOLoop.current().start()
    

    Output:

    {"jsonrpc":"2.0","id":42,"result":["deribit_price_index.btc_usd"],"usIn":1587298852138977,"usOut":1587298852139023,"usDiff":46,"testnet":true}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587298851526,"price":7173.46,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587298852533,"price":7173.53,"index_name":"btc_usd"}}}
    {"jsonrpc":"2.0","id":42,"result":["deribit_price_index.btc_usd"],"usIn":1587298852932540,"usOut":1587298852932580,"usDiff":40,"testnet":true}
    {"jsonrpc":"2.0","method":"subscription","params":{"channel":"deribit_price_index.btc_usd","data":{"timestamp":1587298852533,"price":7173.53,"index_name":"btc_usd"}}}
    

    The example above could be simplified a lot if you integrate the websocket into the DERIBIT class rather than create a separate class for it.

    0 讨论(0)
提交回复
热议问题