Delgan / loguru

Python logging made (stupidly) simple
MIT License
19.99k stars 701 forks source link

_pickle.PicklingError #1105

Closed chongjing001 closed 7 months ago

chongjing001 commented 8 months ago

Hey team,

Getting the following error, how can I solve it? Parsing issues?

Traceback (most recent call last):
  File "D:\env\py311\aiserver_env\Lib\site-packages\loguru\_handler.py", line 204, in emit
    self._queue.put(str_record)
  File "D:\Python\Py311\Lib\multiprocessing\queues.py", line 371, in put
    obj = _ForkingPickler.dumps(obj)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\Py311\Lib\multiprocessing\reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <class 'app_core.utils.exceptions.ReqNetError'>: attribute lookup ReqNetError on app_core.utils.exceptions failed
--- End of logging error ---
# custom exception

raise ReqNetError(f'网络文件[{http_path}]无法下载!请检查')

# except
# The error appears here
self.logger.exception("详情")
Python 3.11
loguru  0.7.2
Delgan commented 7 months ago

Hey @chongjing001.

Do you have a fully reproducible example to share please?

It's not uncommon for custom Exception to be incompatible with pickle if not implemented correctly, see: How to make a custom exception class with multiple init args pickleable.

However, Loguru v0.7.2 implemented a workaround for this and therefore I'm surprised you're encountering this error.

For example, the following code used to produce an error at run-time but works fine with latest version of Loguru:

from loguru import logger
import sys

class MyException(Exception):
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2
        super(MyException, self).__init__(arg1)

logger.remove()
logger.add(sys.stderr, enqueue=True)

try:
    raise MyException("foo", "bar")
except:
    logger.exception("Error")

More details would be welcome please.

chongjing001 commented 7 months ago

Thanks!

a complete example

1. Custom encapsulation

import pathlib
import datetime
from loguru import logger
from config import BASE_DIR, console_output

class Logings:
    __logger = dict()
    __console_output_status = True

    def __init__(self, file_name='info'):

        if Logings.__console_output_status:
            if not console_output:
                logger.remove(handler_id=0)
                Logings.__console_output_status = False

        self.file_name = file_name
        if Logings.__logger.__contains__(file_name):
            self.logger = Logings.__logger[file_name][1]
            return

        date = datetime.datetime.now().strftime('%Y-%m-%d')
        self.__add_logger(date)

    def __add_logger(self, date):
        # 文件名称,按天创建 项目路径下创建logs/{date} 目录保存日志文件
        logpath = f'{BASE_DIR}/logs/{date}'
        # 判断目录是否存在,不存在则创建新的目录
        pathlib.Path(logpath).mkdir(parents=True, exist_ok=True)
        handler_id =logger.add(f'{logpath}/{self.file_name}.log',  # 指定文件
                                # format="{time}  | {level}| {message}",
                                format="{time:YYYY-MM-DD HH:mm:ss} |{level}| {message}",
                                encoding='utf-8',
                                retention='7 days',  # 设置历史保留时长
                                backtrace=True,  # 回溯
                                diagnose=True,  # 诊断
                                enqueue=True,  # 异步写入
                                rotation="5120kb",  # rotation="5kb"  # 切割,设置文件大小,rotation="12:00"  rotation="1 week"
                                filter=lambda record: record["extra"].get("name") == self.file_name  # 过滤模块
                                # compression="zip"   # 文件压缩
                                )
        self.logger = logger.bind(name=self.file_name)
        Logings.__logger[self.file_name] = (handler_id, self.logger, date)

    def __check_update_handler(self):
        if Logings.__logger.__contains__(self.file_name):
            date = datetime.datetime.now().strftime('%Y-%m-%d')
            if date > Logings.__logger[self.file_name][2]:
                logger.remove(Logings.__logger[self.file_name][0])
                self.__add_logger(date)

    def info(self, msg, *args, **kwargs):
        self.__check_update_handler()
        return self.logger.info(msg, *args, **kwargs)

    def debug(self, msg, *args, **kwargs):
        self.__check_update_handler()
        return self.logger.debug(msg, *args, **kwargs)

    def warning(self, msg, *args, **kwargs):
        self.__check_update_handler()
        return self.logger.warning(msg, *args, **kwargs)

    def error(self, msg, *args, **kwargs):
        self.__check_update_handler()
        return self.logger.error(msg, *args, **kwargs)

    def exception(self, msg, *args, exc_info=True, **kwargs):
        self.__check_update_handler()
        return self.logger.exception(msg, *args, exc_info=exc_info, **kwargs)

2. Custom exception

import json
from werkzeug.exceptions import HTTPException

class APIException(HTTPException):
    code = None
    msg = None

    def __init__(self, msg=None, task_guid=None):
        self.msg = msg or self.__class__.__name__
        super(APIException, self).__init__(msg, None)

   @property
    def name(self):
        return self.__class__.__name__

    def get_body(self):
        body = dict(
                code=self.code,
                msg=self.msg
            )
        text = json.dumps(body)
        return text

def gen_error(name: str, err_code: int) -> APIException:
    base_cls = (APIException,)
    cls_attr = {'code': err_code}
    return type(name, base_cls, cls_attr)

ReqNetError = gen_error('ReqNetError', 1014)

3. apply

class TaskDispatch(object):

    def __init__(self, **kwargs):

        self.logger = Logings(self.__class__.__name__)

    def  do_something(self):
        try:
           # do 
           raise ReqNetError(f'网络文件[{http_path}]无法下载!请检查')
        except:
           self.logger.error(f'{self.logger.exception("详情")}')
Delgan commented 7 months ago

Thanks. However, I'm still unable to reproduce your problem.

For one thing, your custom APIException is defined with optional arguments (__init__(self, msg=None, task_guid=None)) and this is one of the workarounds listed in the Stackoverflow link I shared. Therefore, it seems expected to me that I'm unable to trigger the bug.

Secondly, I still believe the bug is present in Loguru 0.7.0 and not 0.7.2. Are you sure you script is running with the Loguru version you're expecting? You can check that by adding print(loguru.__version__) at the beginning of your script.

Lastly, using logger.error(f'{self.logger.exception("详情")}') looks like a mistake. You should simply use self.logger.exception("详情"), and a message with error level will be logged automatically.

chongjing001 commented 7 months ago

Thanks.

I confirm that the version is 0.7.2

I cannot reproduce the problem using a separate example, but this is mandatory in the project. I also feel very strange

Control output abnormal details, unable to record in the log file, PicklingError occurred

The details of the console output are as follows:

0.7.2
2024-04-01 10:57:13.914 | INFO     | app_core.app_logging:info:56 - POST - /sc_elservice/v1.0/itask? | 200
127.0.0.1 - - [01/Apr/2024 10:57:13] "POST /sc_elservice/v1.0/itask HTTP/1.1" 200 -
2024-04-01 10:57:13.942 | INFO     | app_core.app_logging:info:56 - http地址<http://bjjwi.org.cn/okpcq> 下载...
2024-04-01 10:57:14.039 | ERROR    | app_core.app_logging:error:68 - 任务准备出现错误:1014 ReqNetError: 网络文件[http://bjjwi.org.cn/okpcq]无法下载!请检查
2024-04-01 10:57:14.040 | ERROR    | app_core.app_logging:exception:72 - 详情
Traceback (most recent call last):

  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connection.py", line 203, in _new_conn
    sock = connection.create_connection(
           │          └ <function create_connection at 0x0000016862FE0CC0>
           └ <module 'urllib3.util.connection' from 'D:\\env\\py311\\aiserver_env\\Lib\\site-packages\\urllib3\\util\\connection.py'>
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\util\connection.py", line 60, in create_connection
    for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
               │      │           │     │     │       │      └ <SocketKind.SOCK_STREAM: 1>
               │      │           │     │     │       └ <module 'socket' from 'D:\\Python\\Py311\\Lib\\socket.py'>
               │      │           │     │     └ <AddressFamily.AF_UNSPEC: 0>
               │      │           │     └ 80
               │      │           └ 'bjjwi.org.cn'
               │      └ <function getaddrinfo at 0x000001685F2DDDA0>
               └ <module 'socket' from 'D:\\Python\\Py311\\Lib\\socket.py'>
  File "D:\Python\Py311\Lib\socket.py", line 962, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
               │       │           │     │     │       │     │      └ 0
               │       │           │     │     │       │     └ 0
               │       │           │     │     │       └ <SocketKind.SOCK_STREAM: 1>
               │       │           │     │     └ <AddressFamily.AF_UNSPEC: 0>
               │       │           │     └ 80
               │       │           └ 'bjjwi.org.cn'
               │       └ <built-in function getaddrinfo>
               └ <module '_socket' from 'D:\\Python\\Py311\\DLLs\\_socket.pyd'>

socket.gaierror: [Errno 11001] getaddrinfo failed

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connectionpool.py", line 790, in urlopen
    response = self._make_request(
               │    └ <function HTTPConnectionPool._make_request at 0x0000016863078900>
               └ <urllib3.connectionpool.HTTPConnectionPool object at 0x0000016864F93310>
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connectionpool.py", line 496, in _make_request
    conn.request(
    │    └ <function HTTPConnection.request at 0x0000016863074A40>
    └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connection.py", line 395, in request
    self.endheaders()
    │    └ <function HTTPConnection.endheaders at 0x000001685F6CA7A0>
    └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
  File "D:\Python\Py311\Lib\http\client.py", line 1281, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
    │    │            │                            └ False
    │    │            └ None
    │    └ <function HTTPConnection._send_output at 0x000001685F6CA340>
    └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
  File "D:\Python\Py311\Lib\http\client.py", line 1041, in _send_output
    self.send(msg)
    │    │    └ b'GET /okpcq HTTP/1.1\r\nHost: bjjwi.org.cn\r\nUser-Agent: python-requests/2.31.0\r\nAccept-Encoding: gzip, deflate\r\nAccept...
    │    └ <function HTTPConnection.send at 0x000001685F6CA160>
    └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
  File "D:\Python\Py311\Lib\http\client.py", line 979, in send
    self.connect()
    │    └ <function HTTPConnection.connect at 0x00000168630745E0>
    └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connection.py", line 243, in connect
    self.sock = self._new_conn()
    │    │      │    └ <function HTTPConnection._new_conn at 0x00000168630744A0>
    │    │      └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
    │    └ None
    └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connection.py", line 210, in _new_conn
    raise NameResolutionError(self.host, self, e) from e
          │                   │    │     └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
          │                   │    └ <property object at 0x000001686306CD60>
          │                   └ <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>
          └ <class 'urllib3.exceptions.NameResolutionError'>

urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>: Failed to resolve 'bjjwi.org.cn' ([Errno 11001] getaddrinfo failed)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\adapters.py", line 486, in send
    resp = conn.urlopen(
           │    └ <function HTTPConnectionPool.urlopen at 0x0000016863078AE0>
           └ <urllib3.connectionpool.HTTPConnectionPool object at 0x0000016864F93310>
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connectionpool.py", line 844, in urlopen
    retries = retries.increment(
              │       └ <function Retry.increment at 0x0000016862FE3240>
              └ Retry(total=0, connect=None, read=False, redirect=None, status=None)
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\util\retry.py", line 515, in increment
    raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
          │             │      │    │            └ NameResolutionError("<urllib3.connection.HTTPConnection object at 0x0000016864F92D10>: Failed to resolve 'bjjwi.org.cn' ([Err...
          │             │      │    └ NameResolutionError("<urllib3.connection.HTTPConnection object at 0x0000016864F92D10>: Failed to resolve 'bjjwi.org.cn' ([Err...
          │             │      └ '/okpcq'
          │             └ <urllib3.connectionpool.HTTPConnectionPool object at 0x0000016864F93310>
          └ <class 'urllib3.exceptions.MaxRetryError'>

urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='bjjwi.org.cn', port=80): Max retries exceeded with url: /okpcq (Caused by NameResolutionError("<urllib3.connection.HTTPConnection object at 0x0000016864F92D10>: Failed to resolve 'bjjwi.org.cn' ([Errno 11001] getaddrinfo failed)"))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  File "D:\code\py\Flask\sc-aisever\app_core\services\sc_ai_dispatch\sc_dispatch.py", line 275, in _download_file
    r = requests.get(http_path)
        │        │   └ 'http://bjjwi.org.cn/okpcq'
        │        └ <function get at 0x000001686313CA40>
        └ <module 'requests' from 'D:\\env\\py311\\aiserver_env\\Lib\\site-packages\\requests\\__init__.py'>

  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
           │              │           │         └ {}
           │              │           └ None
           │              └ 'http://bjjwi.org.cn/okpcq'
           └ <function request at 0x0000016863139580>
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
           │       │              │           │      └ {'params': None}
           │       │              │           └ 'http://bjjwi.org.cn/okpcq'
           │       │              └ 'get'
           │       └ <function Session.request at 0x00000168631A2700>
           └ <requests.sessions.Session object at 0x0000016864F8BC10>
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
           │    │    │       └ {'timeout': None, 'allow_redirects': True, 'proxies': OrderedDict(), 'stream': False, 'verify': True, 'cert': None}
           │    │    └ <PreparedRequest [GET]>
           │    └ <function Session.send at 0x00000168631A2C00>
           └ <requests.sessions.Session object at 0x0000016864F8BC10>
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
        │       │    │          └ {'timeout': None, 'proxies': OrderedDict(), 'stream': False, 'verify': True, 'cert': None}
        │       │    └ <PreparedRequest [GET]>
        │       └ <function HTTPAdapter.send at 0x00000168631A1F80>
        └ <requests.adapters.HTTPAdapter object at 0x0000016864F90510>
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\adapters.py", line 519, in send
    raise ConnectionError(e, request=request)
          │                          └ <PreparedRequest [GET]>
          └ <class 'requests.exceptions.ConnectionError'>

requests.exceptions.ConnectionError: HTTPConnectionPool(host='bjjwi.org.cn', port=80): Max retries exceeded with url: /okpcq (Caused by NameResolutionError("<urllib3.connection.HTTPConnection object at 0x0000016864F92D10>: Failed to resolve 'bjjwi.org.cn' ([Errno 11001] getaddrinfo failed)"))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  File "D:\Python\Py311\Lib\threading.py", line 995, in _bootstrap
    self._bootstrap_inner()
    │    └ <function Thread._bootstrap_inner at 0x000001685F32A980>
    └ <Thread(Thread-3 (__run_task), started daemon 2744)>
  File "D:\Python\Py311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
    │    └ <function Thread.run at 0x000001685F32A660>
    └ <Thread(Thread-3 (__run_task), started daemon 2744)>
  File "D:\Python\Py311\Lib\threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
    │    │        │    │        │    └ {}
    │    │        │    │        └ <Thread(Thread-3 (__run_task), started daemon 2744)>
    │    │        │    └ ()
    │    │        └ <Thread(Thread-3 (__run_task), started daemon 2744)>
    │    └ <bound method QzDispatch.__run_task of <app_core.services.sc_ai_dispatch.sc_dispatch.QzDispatch object at 0x0000016864F234D0>>
    └ <Thread(Thread-3 (__run_task), started daemon 2744)>

> File "D:\code\py\Flask\sc-aisever\app_core\services\sc_ai_dispatch\sc_dispatch.py", line 641, in __run_task
    self.__upload_to_qz_server()
    └ <app_core.services.sc_ai_dispatch.sc_dispatch.QzDispatch object at 0x0000016864F234D0>

  File "D:\code\py\Flask\sc-aisever\app_core\services\sc_ai_dispatch\sc_dispatch.py", line 415, in __upload_to_qz_server
    path_addr = self._download_file(path_addr)
                │    │              └ 'http://bjjwi.org.cn/okpcq'
                │    └ <function TaskDispatch._download_file at 0x00000168647259E0>
                └ <app_core.services.sc_ai_dispatch.sc_dispatch.QzDispatch object at 0x0000016864F234D0>

  File "D:\code\py\Flask\sc-aisever\app_core\services\sc_ai_dispatch\sc_dispatch.py", line 277, in _download_file
    raise ReqNetError(f'网络文件[{http_path}]无法下载!请检查')
          └ <class 'app_core.utils.exceptions.ReqNetError'>

app_core.utils.exceptions.ReqNetError: 1014 ReqNetError: 网络文件[http://bjjwi.org.cn/okpcq]无法下载!请检查
--- Logging error in Loguru Handler #4 ---
Record was: {'elapsed': datetime.timedelta(seconds=18, microseconds=547013), 'exception': (type=<class 'app_core.utils.exceptions.ReqNetError'>, value=<ReqNetError '1014: ReqNetError'>, traceback=<traceback object at 0x0000016864FA44C0>), 'extra': {'name': 'QzDispatch'}, 'file': (name='app_logging.py', path='D:\\code\\py\\Flask\\sc-aisever\\app_core\\app_logging.py'), 'function': 'exception', 'level': (name='ERROR', no=40, icon='❌'), 'line': 72, 'message': '详情', 'module': 'app_logging', 'name': 'app_core.app_logging', 'process': (id=22620, name='MainProcess'), 'thread': (id=2744, name='Thread-3 (__run_task)'), 'time': datetime(2024, 4, 1, 10, 57, 14, 40911, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '中国标准时间'))}
Traceback (most recent call last):
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connection.py", line 203, in _new_conn
    sock = connection.create_connection(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\util\connection.py", line 60, in create_connection
    for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\Py311\Lib\socket.py", line 962, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
socket.gaierror: [Errno 11001] getaddrinfo failed

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connectionpool.py", line 790, in urlopen
    response = self._make_request(
               ^^^^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connectionpool.py", line 496, in _make_request
    conn.request(
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connection.py", line 395, in request
    self.endheaders()
  File "D:\Python\Py311\Lib\http\client.py", line 1281, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "D:\Python\Py311\Lib\http\client.py", line 1041, in _send_output
    self.send(msg)
  File "D:\Python\Py311\Lib\http\client.py", line 979, in send
    self.connect()
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connection.py", line 243, in connect
    self.sock = self._new_conn()
                ^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connection.py", line 210, in _new_conn
    raise NameResolutionError(self.host, self, e) from e
urllib3.exceptions.NameResolutionError: <urllib3.connection.HTTPConnection object at 0x0000016864F92D10>: Failed to resolve 'bjjwi.org.cn' ([Errno 11001] getaddrinfo failed)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\adapters.py", line 486, in send
    resp = conn.urlopen(
           ^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\connectionpool.py", line 844, in urlopen
    retries = retries.increment(
              ^^^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\urllib3\util\retry.py", line 515, in increment
    raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='bjjwi.org.cn', port=80): Max retries exceeded with url: /okpcq (Caused by NameResolutionError("<urllib3.connection.HTTPConnection object at 0x0000016864F92D10>: Failed to resolve 'bjjwi.org.cn' ([Errno 11001] getaddrinfo failed)"))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\code\py\Flask\sc-aisever\app_core\services\sc_ai_dispatch\sc_dispatch.py", line 275, in _download_file
    r = requests.get(http_path)
        ^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\env\py311\aiserver_env\Lib\site-packages\requests\adapters.py", line 519, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='bjjwi.org.cn', port=80): Max retries exceeded with url: /okpcq (Caused by NameResolutionError("<urllib3.connection.HTTPConnection object at 0x0000016864F92D10>: Failed to resolve 'bjjwi.org.cn' ([Errno 11001] getaddrinfo failed)"))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\code\py\Flask\sc-aisever\app_core\services\sc_ai_dispatch\sc_dispatch.py", line 641, in __run_task
    self.__upload_to_qz_server()
  File "D:\code\py\Flask\sc-aisever\app_core\services\sc_ai_dispatch\sc_dispatch.py", line 415, in __upload_to_qz_server
    path_addr = self._download_file(path_addr)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\code\py\Flask\sc-aisever\app_core\services\sc_ai_dispatch\sc_dispatch.py", line 277, in _download_file
    raise ReqNetError(f'网络文件[{http_path}]无法下载!请检查')
app_core.utils.exceptions.ReqNetError: 1014 ReqNetError: 网络文件[http://bjjwi.org.cn/okpcq]无法下载!请检查

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\env\py311\aiserver_env\Lib\site-packages\loguru\_handler.py", line 204, in emit
    self._queue.put(str_record)
  File "D:\Python\Py311\Lib\multiprocessing\queues.py", line 371, in put
    obj = _ForkingPickler.dumps(obj)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\Py311\Lib\multiprocessing\reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <class 'app_core.utils.exceptions.ReqNetError'>: attribute lookup ReqNetError on app_core.utils.exceptions failed
--- End of logging error ---
Delgan commented 7 months ago

@chongjing001 Is that possible that you inadvertently try to log the error as follows?

try:
    raise ReqNetError("Message")
except Exception as err:
     self.logger.error("An error occurred: {}", err)

That would cause the PicklingError, even with 0.7.2, because err is passed as contextual argument to the logger.

In any case, the best way to solve the problem would be to make your Exception pickleable. You could use the StackOverflow link I shared, and try to fix the following code:

import pickle

pickle.loads(pickle.dumps(ReqNetError("Message")))

If you manage to run the above code without error, it should work within Loguru too since it's roughly executing the same thing.

chongjing001 commented 7 months ago

Thank you very much.

I have found the reason why the custom exception cannot pickleable

gen_error() is placed in the __init__.py file