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
当对象被深度复制时,我得到 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