【发布时间】:2021-03-14 10:57:31
【问题描述】:
我正在尝试每 30 秒向客户端发送一次消息,直到客户端在 django 频道中断开连接。下面是使用 asyncio 编写的一段代码。但是收到错误"AttributeError: 'function' object has no attribute 'send'"。我以前没有使用过 asyncio,所以尝试了很多可能性,所有这些都会导致某种错误(因为我没有经验)。
有人可以帮助我如何解决这个问题。
下面是代码:
class HomeConsumer(WebsocketConsumer):
def connect(self):
self.room_name = "home"
self.room_group_name = self.room_name
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name
)
self.accept()
self.connected = True
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
task = loop.create_task(self.send_response)
loop.run_until_complete(task)
async def send_response(self):
while self.connected:
sent_by = Message.objects.filter(notification_read=False).exclude(
last_sent_by=self.scope["user"]).values("last_sent_by__username")
self.send(text_data=json.dumps({
'notification_by': list(sent_by)
}))
asyncio.sleep(30)
def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name
)
self.connected = False
我认为以下代码部分可能有问题:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
task = loop.create_task(self.send_response)
loop.run_until_complete(task)
使用loop = asyncio.get_event_loop() 而不是创建new_event_loop() 会导致:
RuntimeError: There is no current event loop in thread 'ThreadPoolExecutor-0_0'.
【问题讨论】:
-
您需要
loop.create_task(self.send_response())(注意额外的括号),但是代码仍然很有可能无法按照您的意愿工作,因为run_until_complete(顾名思义)阻塞直到给定任务完成。 -
是的,添加括号有助于调用 send_response 函数。但导致新错误“ RuntimeError: You cannot use AsyncToSync in the same thread as async event loop - just await the async function directly.”
-
如果您已经在事件循环中运行,也许您应该注意错误消息提供的建议。例如,您可以从
AsyncWebsocketConsumer继承,将connect设为async def,将代码修改为here,只需await self.channel_layer.group_add(...)。生成self.send_response和asyncio.create_task(self.send_response())不带run_until_complete。 -
完美。非常感谢您的帮助!
标签: python-3.6 python-asyncio django-channels