【发布时间】:2020-05-08 04:27:17
【问题描述】:
我正在尝试从 Django REST API 方法中获取来自 websocket 服务器(使用 websockets 和 asyncio 实现)的响应。结构如下:
Django 应用
(This does not work, but illustrates the idea)
class AnAPI(views.APIView):
async def get(self, request):
try:
timeout = 5
try:
ws_conn = await asyncio.wait_for(websockets.connect(WS_STRING), timeout)
except ConnectionTimeoutError as e:
<.....>
await ws_conn.send(...)
response = await ws_conn.recv()
ws_conn.close()
return Response(...)
except Exception as e:
print(e)
return Response(...)
WS 服务器
ws_server = websockets.serve(...)
asyncio.get_event_loop().run_until_complete(ws_server)
asyncio.get_event_loop().run_forever()
显然,这使得 Django GET 方法返回 <class 'coroutine'>
AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'coroutine'>`
任何指针将不胜感激!
编辑:感谢所有回答的人!我一直在寻找一个轻量级的解决方案,因为这可能是 Django 应用程序需要与 WS 服务器交互的唯一地方。我最终采用了@Joran 的解决方案,但将所有内容打包到一个辅助函数中,如下所示:
class AnAPI(views.APIView):
def get(self, request):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(my_async_helper_function())
return Response(...)
async def my_async_helper_function():
try:
timeout = 5
try:
ws_conn = await asyncio.wait_for(websockets.connect(WS_STRING), timeout)
except ConnectionTimeoutError as e:
<.....>
await ws_conn.send(...)
response = await ws_conn.recv()
await ws_conn.close()
return ...
except Exception as e:
print(e)
await ws_conn.close()
return ...
【问题讨论】:
-
我认为您不能返回异步端点,可以吗? ...只需摆脱异步,我认为它会起作用...但它更常见于 websockets 一个 js 客户端连接到套接字,而不是一个端点......你基本上失去了几乎所有的好处和痛苦通过像正常的 api 调用一样重复连接到 websockets 的所有不好的部分
-
@JoranBeasley 我之前尝试过,但我想如果我想在函数中使用
await,它会告诉我必须在前面使用async? -
不,我认为您可以使用 asyncio 来调用函数而无需等待...您可能需要更多控件来检测何时建立连接
-
@JoranBeasley 是的,这是一种奇怪的情况,WS 服务器主要与 js 客户端交互,但对于这个特定的端点,如果我能够收集一些仅在该端点上可用的信息,那就太好了WS 服务器..
-
loop = asyncio.new_event_loop(); asyncio.set_event_loop(loop); result = loop.run_until_complete(some_async_fn("django"))(或使用更简单的东西(我很确定那里有一个纯 python websocket-client 包,使用起来非常简单))
标签: python django websocket django-rest-framework