2014-11-17 63 views
0

我有以下代碼:寫pickle.dumps輸出到文件

some_dict = {'a':0, 'b':1} 
line = "some_dict_b = %s\n" % pickle.dumps(some_dict,2) 
exec(line) 
decoded_dict = pickle.loads(some_dict_b) 
decoded_dict == some_dict 

在Python 3這個代碼打印真。在Python 2(2.7.8)中,我在exec行中出現錯誤。我知道轉儲在2.7返回str,同時返回3中的字節流。

我正在編寫一個程序,用於解析輸入文件中的數據,然後創建特定的內存對象並寫出使用這些對象的python腳本。我使用pickle.dumps()將這些對象寫入腳本文件中,並根據上面概述的想法將其插入到變量聲明行中。不過,我需要能夠在Python運行這段代碼2.

我也注意到,在Python 3行變量獲取每個反斜槓正確轉義和類型:

>>> line 
"some_dict_b = b'\\x80\\x02... 

而在Python 2我得到:

>>> line 
'some_dict_b = \x80\x02... 

回答

1

Python的3 bytes類型不已經字符串表示形式,所以,當與%s轉換爲字符串,所述對象表示來代替。如果您想從對象中生成Python兼容的語法,則可以使用%r格式化程序來直接使用該表示法。

在Python 2:

>>> import pickle 
>>> some_dict = {'a':0, 'b':1} 
>>> p = pickle.dumps(some_dict, 2) 
>>> print 'string: %s\nrepresentation: %r' % (p, p) 
string: ?}q(UaqKUbqKu. 
representation: '\x80\x02}q\x00(U\x01aq\x01K\x00U\x01bq\x02K\x01u.' 

在Python 3:

>>> import pickle 
>>> some_dict = {'a':0, 'b':1} 
>>> p = pickle.dumps(some_dict, 2) 
>>> print('string: %s\nrepresentation: %r' % (p, p)) 
string: b'\x80\x02}q\x00(X\x01\x00\x00\x00bq\x01K\x01X\x01\x00\x00\x00aq\x02K\x00u.' 
representation: b'\x80\x02}q\x00(X\x01\x00\x00\x00bq\x01K\x01X\x01\x00\x00\x00aq\x02K\x00u.' 

對象表示(該repr() function的輸出,它使用object.__repr__ special method)通常將試圖爲您提供一個表示該可以粘貼回Python腳本或交互式提示符以重新創建相同的值。

repr()的文檔:

對於許多類型的,這個功能使得試圖返回一個字符串傳遞給eval()時會產生具有相同值的對象,否則表示被一個串括包含對象類型名稱的尖括號以及通常包含對象名稱和地址的附加信息。

這一切都不是特定於pickle,確實如此。

+0

感謝您的詳細解釋,但爲什麼代碼在Python 3中工作?那麼對象的字符串和表示視圖是否一致只是一個巧合? –

+0

@ErwinLavalliére:如果沒有字符串表示(不是'__str__'方法),則使用__repr__'來代替。這完全是一種巧合。 :-) –

0

每當你想到「我使用exec」時,再想一想。你沒有。而不是像這樣評估數據,將數據的內容存儲在字典本身。

然後,將數據顯式指定給變量。

some_dict = {'a':0, 'b':1} 
line = pickle.dumps(some_dict) 
decoded_dict = pickle.loads(line) 
decoded_dict == some_dict 
+0

我打早提交位。 – deets

+0

我明白你在說什麼,但那不完全是我想要的。你會看到,我想在python變量賦值語句中寫入轉儲的輸出,如下所示:「line = 」,稍後要執行,甚至在另一臺計算機中執行。 –

+0

你爲什麼要這樣?除了exec(這很可怕)的安全含義之外,我不認爲你可以擁有對任意創建的變量有意義的代碼。所以要麼你知道你需要哪些變量 - 然後存儲它們的值並加載分配 - 否則你不需要動態數據結構。 – deets

0

在將字符串或字節對象插入行之前,您可以調用repr

# Python 2 
>>> 'some_dict = %s' % repr(pickle.dumps(d)) 
'some_dict = "(dp0\\nS\'a\'\\np1\\nI12\\nsS\'b\'\\np2\\nI24\\ns."' 

# Python 3 
>>> 'some_dict = %s' % repr(pickle.dumps(d)) 
"some_dict = b'\\x80\\x03}q\\x00(X\\x01\\x00\\x00\\x00bq\\x01K\\x18X\\x01\\x00\\x00\\x00aq\\x02K\\x0cu.'" 

或者使用format方法,用!r自動調用repr

>>> 'some_dict = {!r}'.format(pickle.dumps(d)) 
"some_dict = b'\\x80\\x03}q\\x00(X\\x01\\x00\\x00\\x00bq\\x01K\\x18X\\x01\\x00\\x00\\x00aq\\x02K\\x0cu.'" 

(也工作在蟒蛇2)