Getting "TypeError: can't pickle thread.lock objects" when an object is deepcopied with log configs

Getting "TypeError: can't pickle thread.lock objects" when an object is deepcopied with log configs

当对象被深度复制时,我得到 TypeError: can't pickle thread.lock objects。以下是我的 class 结构。

import logging
import copy

DEFAULT_LOG_PATH = r"C:\temp\loging.log"
class LoggerConfig(object):
    def __init__(self, log_obj):
        self._logger = log_obj
        self.default_level = logging.DEBUG
        self.set_default_config()

    def set_default_config(self):
        formatter = self._get_default_formatter()
        self.fh = self._create_file_handler(DEFAULT_LOG_PATH,
                                   self.default_level, formatter)
        self.ch = self._create_stream_handler(self.default_level, formatter)
        self._logger.addHandler(self.fh)
        self._logger.addHandler(self.ch)

    def _get_default_formatter(self):
        msg_format = '%(asctime)s.%(msecs).03d: %(levelname)s:%(message)s'
        date_format = '%d-%b-%y %H:%M:%S'
        formatter = logging.Formatter(msg_format, datefmt=date_format)
        return formatter

    def _create_stream_handler(self, log_level, formatter):
        ch = logging.StreamHandler()
        ch.setLevel(log_level)
        ch.setFormatter(formatter)
        return ch

    def _create_file_handler(self, filename, log_level, formatter):
        fh = logging.FileHandler(filename)
        fh.setLevel(log_level)
        fh.setFormatter(formatter)

        return fh

class DataSpec(object):
    def __init__(self, default=None):
        self.default = copy.deepcopy(default)

class Base(object):
    def __init__(self):
        self.logger = logging.getLogger("logs")
        self.log_config = LoggerConfig(self.logger)

class Simple(Base):
    def Run(self):
        print("In Simple Class")

class Complex(Base):
    def __init__(self):
        s = DataSpec(Simple())

    def Run(self):
        print("In complex")

c = Complex()
c.Run()

DataSpec.init()中发生deepcopy时,出现如下异常。

Traceback (most recent call last):
File "C:/temp/temp.py", line 72, in <module>
    c = Complex()
  File "C:/temp/temp.py", line 67, in __init__
    s = DataSpec(Simple())
  File "C:/temp/temp.py", line 52, in __init__
    self.default = copy.deepcopy(default)
  File "C:\Python27\lib\copy.py", line 190, in deepcopy
    y = _reconstruct(x, rv, 1, memo)
  File "C:\Python27\lib\copy.py", line 334, in _reconstruct
    state = deepcopy(state, memo)
  File "C:\Python27\lib\copy.py", line 163, in deepcopy
    y = copier(x, memo)
  File "C:\Python27\lib\copy.py", line 257, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "C:\Python27\lib\copy.py", line 190, in deepcopy
    y = _reconstruct(x, rv, 1, memo)
  File "C:\Python27\lib\copy.py", line 334, in _reconstruct
    state = deepcopy(state, memo)
  File "C:\Python27\lib\copy.py", line 163, in deepcopy
    y = copier(x, memo)
  File "C:\Python27\lib\copy.py", line 257, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "C:\Python27\lib\copy.py", line 163, in deepcopy
    y = copier(x, memo)
  File "C:\Python27\lib\copy.py", line 230, in _deepcopy_list
    y.append(deepcopy(a, memo))
  File "C:\Python27\lib\copy.py", line 190, in deepcopy
    y = _reconstruct(x, rv, 1, memo)
  File "C:\Python27\lib\copy.py", line 334, in _reconstruct
    state = deepcopy(state, memo)
  File "C:\Python27\lib\copy.py", line 163, in deepcopy
    y = copier(x, memo)
  File "C:\Python27\lib\copy.py", line 257, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "C:\Python27\lib\copy.py", line 190, in deepcopy
    y = _reconstruct(x, rv, 1, memo)
  File "C:\Python27\lib\copy.py", line 334, in _reconstruct
    state = deepcopy(state, memo)
  File "C:\Python27\lib\copy.py", line 163, in deepcopy
    y = copier(x, memo)
  File "C:\Python27\lib\copy.py", line 257, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "C:\Python27\lib\copy.py", line 182, in deepcopy
    rv = reductor(2)
TypeError: can't pickle thread.lock objects

在这里,我看到当我在LogConfig class中注释两个self._logger.addHandler()时,它不会抛出这个错误。任何人都可以帮我找出解决方法吗?我需要添加这些处理程序来保存日志。

终于,我找到了解决办法。在这里,在 Base class 中它需要覆盖 deepcopy 方法并避免深度复制记录器 log_config 对象。 class 如下所示。

class Base(object):
    def __init__(self):
        self.deep_cp_attr = None
        self.logger = logging.getLogger("logs")
        self.log_config = LoggerConfig(self.logger)

    def __deepcopy__(self, memodict={}):
        cpyobj = type(self)() # shallow copy of whole object 
        cpyobj.deep_cp_attr = copy.deepcopy(self.other_attr, memodict) # deepcopy required attr

        return cpyobj