无法腌制日期时间子类
Unable to pickle datetime subclass
我正在尝试 pickle 和 unpickle datetime.datetime
子类对象。但是,它总是会产生错误,我不知道为什么会这样,也不知道如何解决。这是最小的例子:
from datetime import datetime, date, time
class A(datetime):
def __new__(cls, year = 2016, month=1, day=1, hour=0, minute=0, leap_year=False):
return datetime.__new__(cls, year ,month, day, hour, minute)
import pickle
obj = A( month=1, day=1, hour=1, leap_year = False)
serial = pickle.dumps(obj, protocol=pickle.HIGHEST_PROTOCOL)
unpickle = pickle.loads( serial, encoding='bytes')
这将给出以下错误:
TypeError Traceback (most recent call last)
<ipython-input-2-12195a09d83d> in <module>()
5
6
----> 7 unpickle = pickle.loads( serial, encoding='bytes')
<ipython-input-1-605483566b52> in __new__(cls, year, month, day, hour, minute, leap_year)
2 class A(datetime):
3 def __new__(cls, year = 2016, month=1, day=1, hour=0, minute=0, leap_year=False):
----> 4 return datetime.__new__(cls, year ,month, day, hour, minute)
5
TypeError: an integer is required (got type bytes)
有谁知道问题出在哪里以及如何解决?
根据 Pickling Class Instances section of the pickle
module's documentation 中的信息,我能够使以下工作正常进行。从已添加的 __reduce_ex__()
方法返回的值的元组将导致 __new__()
构造函数在 class 实例被 pickle.loads()
调用 unpickled 时被调用——就像当您调用 class.
时通常会发生什么
请注意,我不需要知道 datetime
是否或如何自定义酸洗,也不需要了解其 C 实现。
另请注意,由于您的 leap_year
参数已被问题中的实现忽略(并且不清楚为什么无论如何都需要将其传递给初始化程序),我已将其替换为a Python property
根据当前实例的年份值为其动态计算一个布尔值。
from datetime import datetime, date, time
import pickle
class A(datetime):
def __new__(cls, year=2016, month=1, day=1, hour=0, minute=0):
return datetime.__new__(cls, year, month, day, hour, minute)
def __reduce_ex__(self, protocol):
return (type(self), (self.year, self.month, self.day, self.hour, self.minute))
@property
def is_leapyear(self):
''' Determine if specified year is leap year. '''
year = self.year
if year % 4 != 0:
return False
elif year % 100 != 0:
return True
elif year % 400 != 0:
return False
else:
return True
obj = A(month=1, day=1, hour=1, leap_year=False)
print('calling pickle.dumps()')
serial = pickle.dumps(obj, protocol=pickle.HIGHEST_PROTOCOL)
print('calling pickle.loads()')
unpickle = pickle.loads(serial, encoding='bytes')
print('unpickled {!r}'.format(unpickle)) # -> unpickled A(2016, 1, 1, 1, 0)
print('unpickle.is_leapyear: {}'.format(unpickle.is_leapyear)) # -> True
我正在尝试 pickle 和 unpickle datetime.datetime
子类对象。但是,它总是会产生错误,我不知道为什么会这样,也不知道如何解决。这是最小的例子:
from datetime import datetime, date, time
class A(datetime):
def __new__(cls, year = 2016, month=1, day=1, hour=0, minute=0, leap_year=False):
return datetime.__new__(cls, year ,month, day, hour, minute)
import pickle
obj = A( month=1, day=1, hour=1, leap_year = False)
serial = pickle.dumps(obj, protocol=pickle.HIGHEST_PROTOCOL)
unpickle = pickle.loads( serial, encoding='bytes')
这将给出以下错误:
TypeError Traceback (most recent call last)
<ipython-input-2-12195a09d83d> in <module>()
5
6
----> 7 unpickle = pickle.loads( serial, encoding='bytes')
<ipython-input-1-605483566b52> in __new__(cls, year, month, day, hour, minute, leap_year)
2 class A(datetime):
3 def __new__(cls, year = 2016, month=1, day=1, hour=0, minute=0, leap_year=False):
----> 4 return datetime.__new__(cls, year ,month, day, hour, minute)
5
TypeError: an integer is required (got type bytes)
有谁知道问题出在哪里以及如何解决?
根据 Pickling Class Instances section of the pickle
module's documentation 中的信息,我能够使以下工作正常进行。从已添加的 __reduce_ex__()
方法返回的值的元组将导致 __new__()
构造函数在 class 实例被 pickle.loads()
调用 unpickled 时被调用——就像当您调用 class.
请注意,我不需要知道 datetime
是否或如何自定义酸洗,也不需要了解其 C 实现。
另请注意,由于您的 leap_year
参数已被问题中的实现忽略(并且不清楚为什么无论如何都需要将其传递给初始化程序),我已将其替换为a Python property
根据当前实例的年份值为其动态计算一个布尔值。
from datetime import datetime, date, time
import pickle
class A(datetime):
def __new__(cls, year=2016, month=1, day=1, hour=0, minute=0):
return datetime.__new__(cls, year, month, day, hour, minute)
def __reduce_ex__(self, protocol):
return (type(self), (self.year, self.month, self.day, self.hour, self.minute))
@property
def is_leapyear(self):
''' Determine if specified year is leap year. '''
year = self.year
if year % 4 != 0:
return False
elif year % 100 != 0:
return True
elif year % 400 != 0:
return False
else:
return True
obj = A(month=1, day=1, hour=1, leap_year=False)
print('calling pickle.dumps()')
serial = pickle.dumps(obj, protocol=pickle.HIGHEST_PROTOCOL)
print('calling pickle.loads()')
unpickle = pickle.loads(serial, encoding='bytes')
print('unpickled {!r}'.format(unpickle)) # -> unpickled A(2016, 1, 1, 1, 0)
print('unpickle.is_leapyear: {}'.format(unpickle.is_leapyear)) # -> True