有没有办法让python pickle忽略“它不是同一个对象”的错误

时间:2011-12-05 04:30:27

标签: python datetime mocking pickle

有没有办法让python pickle忽略“它不是同一个对象”错误?

我正在使用Mock编写一个测试,对datetime.utcnow()产生的结果进行细粒度控制。我正在使用的代码是时间敏感的,因此mock的补丁使其易于测试。

相同的测试需要pickle对象并将结果发送到远程服务器。出于测试的目的,如果远程服务器腌制并接收标准日期时间,一切都会好的。

不幸的是,pickle模块正在发生以下错误:

  

不能pickle< type'datetime.datetime'>:它不是同一个对象   datetime.datetime

这是重现错误的最小示例。

from mock import patch
from datetime import datetime
import pickle

class MockDatetime(datetime):
  frozendt = datetime(2011,05,31)

  @classmethod
  def advance(cls, **kw):
    cls.frozendt = cls.frozendt + timedelta(**kw)

  @classmethod
  def utcnow(cls):
    return cls.frozendt

@patch('datetime.datetime', MockDatetime)
def test():
  pickle.dumps(datetime.utcnow())

if __name__ == '__main__':
  test()

是否有一些__reduce____getstate__方法的组合可能会让腌制机器误以为MockDatetime是我腌制的日期时间?

2 个答案:

答案 0 :(得分:5)

查看文档中的where to patch部分,我看到了这个建议:

  

基本原则是你修补一个对象使用的位置,它不一定与定义它的位置相同。

按照这个建议,我试图替换:

@patch('datetime.datetime', MockDatetime)

使用:

@patch('__main__.datetime', MockDatetime)

我没有从pickle收到任何错误。另外,我添加了一个print语句,以确保datetime真正被修补,我得到了预期值。

答案 1 :(得分:2)

如果有人想要一个通用的解决方案来腌制嘲笑:

m = mock.MagicMock()
m.__reduce__ = lambda self: (mock.MagicMock, ())

请注意,这似乎不会保存使用过的模拟的内部内容(例如调用)。