Python websockets: how to override sync method WebSocketCommonProtocol.connection_made() with async call?
Clash 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.
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.
To make an async call (call an async function) from a sync function running inside the event loop, such as
connection_made
, useloop.create_task(async_function(args...))
. You won't be able to see the result becauseconnection_made
must return as soon as possible to allow the event loop to proceed.– user4815162342
Aug 11 at 6:35