【问题标题】:Python websockets: how to override sync method WebSocketCommonProtocol.connection_made() with async call?Python websockets:如何使用异步调用覆盖同步方法 WebSocketCommonProtocol.connection_made()?
【发布时间】:2018-08-10 04:05:09
【问题描述】:

目前WebSocketCommonProtocol.connection_made() 被定义为同步调用。如果我想覆盖它并添加一些异步调用,似乎没有办法。

示例:我使用 aioredis 与 Redis 对话;但是在覆盖WebSocketCommonProtocol.connection_made() 时我不能使用aioredis。我能想到的唯一解决方法是在这个函数中使用同步库 redis-py,但在其他地方使用 aioredis。它有效,但非常丑陋。

asgiref.sync.async_to_sync() 在这里不起作用:我已经运行了事件循环。此提交将阻止我使用它:https://github.com/django/asgiref/commit/9d42cb57129bd8d94a529a5c95dcf9f5d35a9beb

WebSocketCommonProtocol.connection_made() 继承自 asyncio.StreamReaderProtocol.connection_made()。因此,即使对于 python 标准库,这也是一个通用问题。不知道有没有人知道解决方案。

请给我一些解决这个问题的建议。

【问题讨论】:

  • 要从在事件循环中运行的同步函数(例如connection_made)进行异步调用(调用异步函数),请使用loop.create_task(async_function(args...))。您将看不到结果,因为connection_made 必须尽快返回以允许事件循环继续进行。

标签: python websocket python-asyncio


【解决方案1】:

制定了一种解决方案:https://pypi.org/project/syncasync/

它将在新线程中运行异步代码。所以它不会与同步代码有竞争条件。这种方式很慢:主线程会等待同步代码,同步代码会等待新线程完成。

与其他解决方案相比:在您的程序中同时使用同步库和异步库,此解决方案将允许您仅使用异步库。

试一试,让我知道任何错误,或提出更好的方法。

例子:

#!/usr/bin/env python

import asyncio

from syncasync import async_to_sync


class Base:
    def method(self):
        pass

    def run(self):
        self.method()


class Derived(Base):
    @async_to_sync
    async def method(self):
        await asyncio.sleep(0)


async def test():
    d = Derived()
    d.run()


if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(test())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    相关资源
    最近更新 更多