RecursionError:超出最大递归深度 | [上一行重复了 972 次以上] |套接字.io

问题描述 投票:0回答:1

我需要帮助,为什么我会收到类似

RecursionError
的错误,我正在使用
python-socket

顺便说一句,在继续之前,我想澄清这个问题不是因为套接字配置,它工作正常,简单的测试事件工作正常。

这是我监听特定事件的套接字事件:

@sio_server.on(EVENT.REPLY_ON_TICKET)
async def reply_on_ticket_event(sid:str, data:dict):
    
    sender_id = None
    if data["sender_info"]["sender_id"]:
        sender_id= data["sender_info"]["sender_id"]
    else:
        sender_id= data["sender_id"]
        
    payload = {
        "ticket_id": data["ticket_id"],
        "sender_id": sender_id,
        "notify": data["notify"],
        "reply": data["reply"],
    }
    # Obtain a database session manually
    db_session = next(get_db())
    res = await reply_on_ticket_service(payload, db_session)
    if res["success"]:
        # the callback data for client socket
        return {
                    "status_code": 200,
                    "success": True,
                    "message": "reply data",
                    "payload": res["data"],
                }
    
    return {"status_code": 400, "success": False}  

  

这里是处理回复票证流程的服务:


async def reply_on_ticket_service(data:dict, db_session: Session = Depends(get_db)):
    try:
        new_reply= TicketReplyModal(reply_text=data["reply"],ticket_id=data["ticket_id"],sender_id=data["sender_id"])
        
        new_reply_id= await db_manager.add_record(new_reply,db_session)
        if not new_reply_id:
            return {"success":False, 'status_code':400, "message":"Error occurred while creating new replay"} 
        new_record= await db_manager.get_record_by_id(new_reply_id, TicketReplyModal,db_session)
        if not new_record:
            return {"success":False, 'status_code':404, "message":"Unable to find record with newly created replay"} 
            
        sender_data = db_session.query(UserModel).filter(UserModel.id == new_record.sender_id).first()
        if not sender_data:
            return {"success":False, 'status_code':404, "message":"Unable to find sender info"} 
        
        reply = {
            "id":new_record.id,
            "created_at":new_record.created_at,
            "reply_text":new_record.reply_text,
            "ticket_id": new_record.ticket_id,
            "sender":{
                "id": sender_data.id,
                "email": sender_data.email,
                "profile_image": sender_data.profile_image,
                "username": sender_data.username,
                "public_key": sender_data.public_key,
            }

        }
        
        return {"success": True, "data": reply}
        

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    

reply_on_ticket_event
返回方法中,如果我注释该行
"payload": res["data"]
然后它就可以正常工作,没有任何问题:

错误代码片段:

Task exception was never retrieved
future: <Task finished name='Task-39' coro=<AsyncServer._handle_event_internal() done, defined at C:\Users\AK\.virtualenvs\BE-hVO0_cLf\Lib\site-packages\socketio\async_server.py:605> exception=RecursionError('maximum recursion depth exceeded')>
Traceback (most recent call last):
  File "C:\Users\AK\.virtualenvs\BE-hVO0_cLf\Lib\site-packages\socketio\async_server.py", line 617, in _handle_event_internal
    await server._send_packet(eio_sid, self.packet_class(
  File "C:\Users\AK\.virtualenvs\BE-hVO0_cLf\Lib\site-packages\socketio\async_server.py", line 518, in _send_packet
    encoded_packet = pkt.encode()
                     ^^^^^^^^^^^^
  File "C:\Users\AK\.virtualenvs\BE-hVO0_cLf\Lib\site-packages\socketio\packet.py", line 64, in encode
    encoded_packet += self.json.dumps(data, separators=(',', ':'))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\__init__.py", line 238, in dumps
    **kw).encode(obj)
          ^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\encoder.py", line 200, in encode
    chunks = self.iterencode(o, _one_shot=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\encoder.py", line 258, in iterencode
    return _iterencode(o, 0)
           ^^^^^^^^^^^^^^^^^
  File "D:\BE\app.py", line 38, in default
    return super().default(obj)
           ^^^^^^^^^^^^^^^^^^^^
  File "D:\BE\app.py", line 38, in default
    return super().default(obj)
           ^^^^^^^^^^^^^^^^^^^^
  File "D:\BE\app.py", line 38, in default
    return super().default(obj)
           ^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 972 more times]
RecursionError: maximum recursion depth exceeded

错误所指向的行位于app.py中

class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, uuid.UUID):
            return str(obj)
        return super().default(obj)
    

@app.on_event("startup")
def startup_event():
    json.JSONEncoder.default = CustomJSONEncoder().default

我尝试注释上面的@app.on_event(“startup”),然后执行该套接字事件,然后这里抱怨UUID的错误是错误输出:

Task exception was never retrieved
future: <Task finished name='Task-47' coro=<AsyncServer._handle_event_internal() done, defined at C:\Users\AK\.virtualenvs\pw7-BE-hVO0_cLf\Lib\site-packages\socketio\async_server.py:605> exception=TypeError('Object of type UUID is not JSON serializable')>
Traceback (most recent call last):
  File "C:\Users\AK\.virtualenvs\pw7-BE-hVO0_cLf\Lib\site-packages\socketio\async_server.py", line 617, in _handle_event_internal
    await server._send_packet(eio_sid, self.packet_class(
  File "C:\Users\AK\.virtualenvs\pw7-BE-hVO0_cLf\Lib\site-packages\socketio\async_server.py", line 518, in _send_packet
    encoded_packet = pkt.encode()
                     ^^^^^^^^^^^^
  File "C:\Users\AK\.virtualenvs\pw7-BE-hVO0_cLf\Lib\site-packages\socketio\packet.py", line 64, in encode
    encoded_packet += self.json.dumps(data, separators=(',', ':'))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\__init__.py", line 238, in dumps
    **kw).encode(obj)
          ^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\encoder.py", line 200, in encode
    chunks = self.iterencode(o, _one_shot=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\encoder.py", line 258, in iterencode
    return _iterencode(o, 0)
           ^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\encoder.py", line 180, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type UUID is not JSON serializable
python sockets websocket fastapi asgi
1个回答
0
投票

您遇到的问题与此行有关:

json.JSONEncoder.default = CustomJSONEncoder().default

这会将

default
中的
JSONEncoder
方法替换为最初为您的
CustomJSONEncoder
子类编写的自定义版本。但是,该子类版本调用
super()
,它会在其基类中查找实现。基类是
JSONEncoder
,所以在你进行方法替换之后,它最终会找到自己。因此,当你有一个不可编码的值时,你不会得到预期的
TypeError
,你会得到递归,直到达到极限并得到
RecursionError

至于如何解决这个问题,我认为有两种选择。解决当前症状的一种方法是将对

super().default(obj)
的调用替换为显式
raise TypeError
调用(可能带有描述无法编码的对象的消息)。

但是,除了让您找到触发问题的虚假数据之外,这并不能真正解决方法替换的潜在问题。另一种选择是弄清楚如何正确地将

CustomJSONEncoder
类传递到库框架,以便它将使用它而不是标准库中的原始编码器。这样你就可以继续以推荐的风格编写你自己的
default
方法,而不会因为替换
json.JSONEncoder.default
而破坏东西。

© www.soinside.com 2019 - 2024. All rights reserved.