2017-02-02 9 views
6

на основе this answer Я хочу построить клиент асинхронной websoket в классе, который будет импортироваться из другого файла:Как вызвать функцию async, содержащуюся в классе?

#!/usr/bin/env python3 

import sys, json 
import asyncio 
from websockets import connect 

class EchoWebsocket: 
    def __await__(self): 
     # see: https://stackoverflow.com/a/33420721/1113207 
     return self._async_init().__await__() 

    async def _async_init(self): 
     self._conn = connect('wss://ws.binaryws.com/websockets/v3') 
     self.websocket = await self._conn.__aenter__() 
     return self 

    async def close(self): 
     await self._conn.__aexit__(*sys.exc_info()) 

    async def send(self, message): 
     await self.websocket.send(message) 

    async def receive(self): 
     return await self.websocket.recv() 

class mtest: 
    async def start(self): 
     try: 
      self.wws = await EchoWebsocket() 
     finally: 
      await self.wws.close() 

    async def get_ticks(self): 
     await self.wws.send(json.dumps({'ticks_history': 'R_50', 'end': 'latest', 'count': 1})) 
     return await self.wws.receive() 

if __name__ == '__main__': 
    a = mtest() 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(a.start()) 

И я импортировать его в main.py, где я следующее:

from testws import * 

a = mtest() 
print (a.get_ticks()) 
print ("this will be printed after the ticks") 

Но он извлекает мне следующую ошибку:

[email protected]:/home/dinocob# python3 test.py 
<coroutine object hello.get_ticks at 0x7f13190a9200> 
test.py:42: RuntimeWarning: coroutine 'mtest.get_ticks' was never awaited 
    print (a.get_ticks()) 
this will be printed after the ticks 

что здесь происходит? Почему я не могу получить доступ к mtest.get_ticks, если у него есть слово async в начале def?

+0

Вам нужно использовать 'await', когда вы его вызываете. – dirn

+0

Я получил синтаксическую ошибку при вызове функции следующим образом: 'foo = await a.get_ticks()' ... – harrison4

+1

Вы не можете использовать 'await' вне сопроцессора. Если вы пытаетесь выполнить сопрограмму вне другой, вам нужно запланировать ее с помощью цикла событий (например, 'loop.run_until_complete (a.get_ticks())). – dirn

ответ

5

Наконец я смог найти правильный способ сделать это (особая благодарность @dirn)

#!/usr/bin/env python3 

import sys, json 
import asyncio 
from websockets import connect 

class EchoWebsocket: 
    async def __aenter__(self): 
     self._conn = connect('wss://ws.binaryws.com/websockets/v3') 
     self.websocket = await self._conn.__aenter__()   
     return self 

    async def __aexit__(self, *args, **kwargs): 
     await self._conn.__aexit__(*args, **kwargs) 

    async def send(self, message): 
     await self.websocket.send(message) 

    async def receive(self): 
     return await self.websocket.recv() 

class mtest: 
    def __init__(self): 
     self.wws = EchoWebsocket() 
     self.loop = asyncio.get_event_loop() 

    def get_ticks(self): 
     return self.loop.run_until_complete(self.__async__get_ticks()) 

    async def __async__get_ticks(self): 
     async with self.wws as echo: 
      await echo.send(json.dumps({'ticks_history': 'R_50', 'end': 'latest', 'count': 1})) 
      return await echo.receive() 

И это в main.py:

from testws import * 

a = mtest() 

foo = a.get_ticks() 
print (foo) 

print ("async works like a charm!") 

foo = a.get_ticks() 
print (foo) 

Это выход:

[email protected]:/home/dinocob# python3 test.py 
{"count": 1, "end": "latest", "ticks_history": "R_50"} 
async works like a charm! 
{"count": 1, "end": "latest", "ticks_history": "R_50"} 

Любой отзыв для улучшения приветствуется! ;)

 Смежные вопросы

  • Нет связанных вопросов^_^