无法pickle datetime子类

2024-10-10 18:24:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试pickle和unpickledatetime.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)

有人知道问题出在哪里,怎么解决吗?你知道吗


Tags: importfalsenewdatetimebytes错误serialyear
1条回答
网友
1楼 · 发布于 2024-10-10 18:24:10

基于pickle模块的documentationPickling Class Instances部分中的信息,我能够实现以下功能。从添加的__reduce_ex__()方法返回的值的元组将导致在类实例被pickle.loads()调用取消勾选时调用__new__()构造函数,就像调用类时通常发生的情况一样。你知道吗

注意,我不需要知道datetime是否或者如何定制pickling,也不需要了解它的C实现。你知道吗

另请注意,由于您的问题中的实现忽略了leap_year参数(不清楚为什么需要将其传递给初始值设定项),因此我用Python property替换了它,它根据当前实例的year值动态计算布尔值。你知道吗

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

相关问题 更多 >