2013-01-14 35 views
2

我有一個列表的列表,每個子列表看起來像這樣:的Python - cPickle的嵌套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] 

醃名單:

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之前的打印語句表明錯誤發生在這裏,而不是其他地方。

docs,它聽起來像你可以cPickle嵌套對象,並不是所有的都必須是內置類型。也許我可以將所有datetime對象更改爲字符串。毫無疑問,有許多方法可以完成序列化,並且我可以調整代碼以使上述不成問題。但是,我需要明白爲什麼這是不可能的,如果確實如此。

任何人都可以解釋爲什麼嵌套的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 

我映射此功能在其他模塊的其他數據,因此,最好想保持酸洗一個函數調用裏面。

+2

請發佈更多信息 - 例如,您使用的Python版本是什麼,因爲您的數據結構在2.7.3和3.3.0下都適合我。 –

+0

+1 to @ t.drrownik。而2.5.6和PyPy 1.9.0/2.7.2,都可以正常工作。而且我隱約記得從datetime import datetime'可能會混淆事物的錯誤,我認爲它在2.3或2.4中是固定的。 – abarnert

+0

另外,它是否實際上在'cPickle.dump'調用中引發這個異常,而不是(a)在'cPickle.load'中提早定義值,或者(b)完全不同的地方?你能打印一個完整的回溯而不是一行,理想情況下(它不會太慢,如果你可以使用一個小的數據集來重現它)用'pickle'而不是'cPickle'來完成? – abarnert

回答

0

運行與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. 

所以從那裏開始慢慢擴展它,看看你的代碼中斷。

0

要做到這一點,我不會做任何複雜的事情......我會寫你想寫的代碼。我會使用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]] 

蘿也有some good tools幫助您瞭解是什麼原因導致你的酸洗當你的代碼沒有失敗。