Использование WebSockets и Python-can с asyncio - PullRequest
0 голосов
/ 27 августа 2018

Целью является создание приложения, которое обрабатывает данные с WebSocket и CAN-шины. Я использую websockets, который является асинхронным, но библиотека python-can синхронизируется, и именно здесь начинаются проблемы.

Единственный способ, который я понял, - это использовать декораторы, которые преобразуют функции синхронизации в асинхронные и наоборот.

В упрощенном примере ниже: сервер получает сообщение по шине can -> сервер отправляет сообщение на ws.

WebSocket.py:

async def websocket_handler(websocket, path):
    # ...

async def send(data):
    await client.send(json.dumps(data))

def init():
    return websockets.serve(websocket_handler, 'localhost', 6969)

CAN.py:

_bus = None

@force_sync
async def on_message_received(msg):
    # ...
    await WebSocket.send(...)

@force_async
def handle_messages():
    while True:
        msg = _bus.recv()
        if msg is not None:
            print(msg)
            on_message_received(msg)

async def init():
    global _bus
    _bus = Bus('test', bustype='virtual')
    await handle_messages()

декораторы:

def force_async(fn):
    pool = ThreadPoolExecutor()

    def wrapper(*args, **kwargs):
        future = pool.submit(fn, *args, **kwargs)
        return asyncio.wrap_future(future)

    return wrapper


def force_sync(fn):

    def wrapper(*args, **kwargs):
        res = fn(*args, **kwargs)
        if asyncio.iscoroutine(res):
            return asyncio.new_event_loop().run_until_complete(res)
        return res

    return wrapper

main.py:

asyncio.get_event_loop().run_until_complete(asyncio.gather(
    CAN.init(),
    WebSocket.init(),
    can_test.init()
))

asyncio.get_event_loop().run_forever()

Я новичок в Python, но выглядит ужасно неправильно. Есть ли правильный способ сделать это?

...