【问题标题】:Python - cPickle nested datetime objectsPython - cPickle 嵌套日期时间对象
【发布时间】:2013-01-14 23:00:06
【问题描述】:

我有一个列表列表,每个子列表看起来像这样:

a = [datetime.datetime(2012, 2, 1), datetime.datetime(2012, 2, 2), 'string', 4.00]
b = [datetime.datetime(2012, 3, 1), datetime.datetime(2012, 3, 4), 'another_string', 5.00]

list_of_lists = [a,b]

腌制列表:

cPickle.dump(list_of_lists, open(filename, 'wb')) #filename defined 

运行时,它会引发:

Traceback (most recent call last):
  File "analyze_data.py", line 129, in <module>
    analyze_data(sys.argv[1]) #because the dump runs inside a function
  File "analyze_data.py", line 77, in analyze_data
    cPickle.dump(list_of_lists, open(filename, 'wb')) 
TypeError: 'datetime.datetime' object is not callable

我已经在 Python 2.7.3 和 2.6.8 上复制了该错误。

与常规泡菜相同的错误/回溯。此外,紧接在 cPickle.dump 之前的 print 语句表明错误发生在这里而不是其他地方。

docs 看来,您可以 cPickle 嵌套对象,并非所有对象都必须是内置类型。也许我可以将所有datetime 对象更改为字符串。毫无疑问,有很多方法可以完成序列化,我可以调整代码以使上述问题不存在。但是,如果确实如此,我需要了解为什么这是不可能的。

谁能解释为什么嵌套的日期时间对象不能通过 cPickle/pickle 序列化?

编辑:腌制上述数据结构在函数之外工作正常。里面,没有骰子。见下文。

def analyze_data(some_id, some_date=default_date): #some_id/some_date (datetime object) defined above
  …
  #create list_of_lists
  …
  string_date = some_date.strftime('%Y%m%d') #works
  filename = '{0}_{1}.p'.format(some_id, string_date) #filename created fine
  cPickle.dump(list_of_lists, open(filename, 'wb')) #kaboom

我将此函数映射到其他模块中的其他数据,因此理想情况下希望将酸洗保留在函数调用中。

【问题讨论】:

  • 请发布更多信息 - 例如,您使用的是什么 Python 版本,因为您的数据结构在 2.7.3 和 3.3.0 下对我来说都是可选的。
  • +1 到@t.dubrownik。 2.5.6 和 PyPy 1.9.0/2.7.2 也都可以正常工作。而且我隐约记得from datetime import datetime 可能会混淆事物的错误,我认为这已在 2.3 或 2.4 中修复。
  • 另外,它实际上是否在 cPickle.dump 调用中引发了该异常,而不是 (a) 早期,当您定义值时,或者 (b) 在某个完全不同的地方,在 @987654329 @?你能打印一个完整的回溯而不是一行吗?理想情况下(如果你可以使用这么小的数据集来重现它不会太慢)使用pickle而不是cPickle
  • 紧接在cPickle.dump() 之前的repr(list_of_lists) 是什么?
  • @t.dubrownik - 将python版本放在上面,还添加了编辑结构如何在函数外腌制。

标签: python datetime pickle


【解决方案1】:

使用python2.7 test.py 运行以下命令:

# encoding: utf-8
# SO 14328382
import cPickle
import datetime

default_date = datetime.datetime.now()

def analyze_data(some_id, some_date=default_date): #some_id/some_date (datetime object) defined above
    #…
    #create list_of_lists
    #…
    a = [datetime.datetime(2012, 2, 1), datetime.datetime(2012, 2, 2), 'string', 4.00]
    b = [datetime.datetime(2012, 3, 1), datetime.datetime(2012, 3, 4), 'another_string', 5.00]
    list_of_lists = [a,b]

    string_date = some_date.strftime('%Y%m%d') #works
    filename = '{0}_{1}.p'.format(some_id, string_date) #filename created fine
    cPickle.dump(list_of_lists, open(filename, 'wb')) #kaboom

analyze_data('abc', datetime.datetime(2013,3,12))

不会抛出错误,而是生成文件abc_20130312.p,内容为:

(lp1
(lp2
cdatetime
datetime
p3
(S'\x07\xdc\x02\x01\x00\x00\x00\x00\x00\x00'
tRp4
ag3
(S'\x07\xdc\x02\x02\x00\x00\x00\x00\x00\x00'
tRp5
aS'string'
p6
aF4
aa(lp7
g3
(S'\x07\xdc\x03\x01\x00\x00\x00\x00\x00\x00'
tRp8
ag3
(S'\x07\xdc\x03\x04\x00\x00\x00\x00\x00\x00'
tRp9
aS'another_string'
p10
aF5
aa.

所以从那里开始,慢慢扩展它,看看你的代码在哪里中断。

【讨论】:

    【解决方案2】:

    为此,我不会做任何复杂的事情...我会编写您想要编写的代码。我会使用dill,它几乎可以序列化python中的任何东西。

    >>> import dill
    >>> import datetime
    >>> a = [datetime.datetime(2012, 2, 1), datetime.datetime(2012, 2, 2), 'string', 4.00]
    >>> b = [datetime.datetime(2012, 3, 1), datetime.datetime(2012, 3, 4), 'another_string', 5.00]
    >>> 
    >>> list_of_lists = [a,b]
    >>> 
    >>> lol = dill.loads(dill.dumps(list_of_lists))
    >>> lol
    [[datetime.datetime(2012, 2, 1, 0, 0), datetime.datetime(2012, 2, 2, 0, 0), 'string', 4.0], [datetime.datetime(2012, 3, 1, 0, 0), datetime.datetime(2012, 3, 4, 0, 0), 'another_string', 5.0]]
    >>>
    >>> default_date = datetime.datetime.today()
    >>> 
    >>> def analyze_data(some_id, some_date=default_date):
    ...     string_date = some_date.strftime('%Y%m%d')
    ...     filename = '{0}_{1}.p'.format(some_id, string_date)
    ...     return dill.loads(dill.dumps(list_of_lists))
    ... 
    >>> # no kaboom
    >>> analyze_data('123')
    [[datetime.datetime(2012, 2, 1, 0, 0), datetime.datetime(2012, 2, 2, 0, 0), 'string', 4.0], [datetime.datetime(2012, 3, 1, 0, 0), datetime.datetime(2012, 3, 4, 0, 0), 'another_string', 5.0]]
    

    Dill 还拥有some good tools,可帮助您了解在代码失败时导致酸洗失败的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-22
      相关资源
      最近更新 更多