Python websockets: how to override sync method WebSocketCommonProtocol.connection_made() with async call?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Python websockets: how to override sync method WebSocketCommonProtocol.connection_made() with async call?



Currently WebSocketCommonProtocol.connection_made() is defined as a sync call. If I want override it and add some async call, it seems no way to do it.


WebSocketCommonProtocol.connection_made()



Example: I use aioredis to talk to Redis; but I cannot use aioredis when overriding WebSocketCommonProtocol.connection_made(). The only workaround I can think out is using a sync library redis-py in this function, but use aioredis in other places. It works but very ugly.


WebSocketCommonProtocol.connection_made()



asgiref.sync.async_to_sync() doesn't work here: I already have event loop running. This commit will prevent me from using it: https://github.com/django/asgiref/commit/9d42cb57129bd8d94a529a5c95dcf9f5d35a9beb


asgiref.sync.async_to_sync()



WebSocketCommonProtocol.connection_made() is inherited from asyncio.StreamReaderProtocol.connection_made(). So this is a generic question even for python standard library. Don't know whether anyone knows a solution already.


WebSocketCommonProtocol.connection_made()


asyncio.StreamReaderProtocol.connection_made()



Please give me some suggestions to solve this issue.





To make an async call (call an async function) from a sync function running inside the event loop, such as connection_made, use loop.create_task(async_function(args...)). You won't be able to see the result because connection_made must return as soon as possible to allow the event loop to proceed.
– user4815162342
Aug 11 at 6:35



connection_made


loop.create_task(async_function(args...))


connection_made




1 Answer
1



Worked out one solution: https://pypi.org/project/syncasync/



It will run the async code in a new thread. So it will not have a race condition with the sync code. This approach is very slow: the main thread will wait for the sync code, and the sync code will wait for the new thread to finish.



Compared to the other solution: use both sync and async libraries in your program, this solution will allow you to only use async library.



Give it a try and let me know any bugs, or suggest a better approach.



Example:


#!/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())






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard