loguru icon indicating copy to clipboard operation
loguru copied to clipboard

TypeError: __init__() missing 2 required keyword-only arguments: 'request' and 'response'

Open RonaldinhoL opened this issue 4 years ago • 2 comments

l got error sometimes, but not 100%

--- Logging error in Loguru Handler #1 ---
Record was: None
Traceback (most recent call last):
  File "C:\Users\Ronaldinho\.virtualenvs\xxx-5Vbn2Ffj\lib\site-packages\loguru\_handler.py", line 270, in _queued_writer
    message = queue.get()
  File "c:\users\ronaldinho\.pyenv\pyenv-win\versions\3.9.6\lib\multiprocessing\queues.py", line 368, in get
    return _ForkingPickler.loads(res)
  File "C:\Users\Ronaldinho\.virtualenvs\xxx-5Vbn2Ffj\lib\site-packages\loguru\_recattrs.py", line 77, in _from_pickled_value
    value = pickle.loads(pickled_value)
TypeError: __init__() missing 2 required keyword-only arguments: 'request' and 'response'
--- End of logging error ---

is it because of my log content is not serializable? but i even don't know this is occur in which line it attempt to log...

RonaldinhoL avatar Sep 11 '21 01:09 RonaldinhoL

This is due to log not being deserializable. The serialization process sending the message to the queue works fine, but at the time it needs to be retrieved and logged from within the thread, it fails. That's why you can see Record was: None. Unfortunately, the logging thread isn't able to retrieve the logged object so it can't display any useful information about its origin.

This is not the first time this problem has been reported (see #329). It's hard to find a solution, but I think I'll have to modify the serialization function, so that it's done in two steps (first file+line which can't fail, then the remaining record data, and print basic info if later fails).

In the meantime, you can identify the failing logging call by temporarily adding a custom sink (it mimics enqueue=True in the main thread so record will be fully displayed on error):

import pickle

def debugging_sink(message):
    pickle.loads(pickle.dumps(message))

logger.add(debugging_sink, enqueue=False)

Most of time, the error is due to an Exception subclass (see Cannot unpickle Exception subclass).

Once the origin is identified, you can fix it like that:

try:
    faulty_function()
except Exception:
    type, _, tb = sys.exc_info()
    logger.opt(exception=(type, None, tb)).error("An error occurred")

You can also apply the fix globally as follow:

def patcher(record):
    exception = record["exception"]
    if exception is not None:
        fixed = Exception(str(exception.value))
        record["exception"] = exception._replace(value=fixed)

logger.configure(patcher=patcher)

Delgan avatar Sep 11 '21 08:09 Delgan

ok i will keep tracking it, thank you

RonaldinhoL avatar Sep 14 '21 14:09 RonaldinhoL