2010-05-18 22 views
3

我知道這不是醃製模塊是如何使用的,但我原以爲這會起作用。我使用Python 3.1.2爲什麼不添加二元酸菜工作?

這裏的後臺代碼:

import pickle 

FILEPATH='/tmp/tempfile' 

class HistoryFile(): 
    """ 
    Persistent store of a history file 
    Each line should be a separate Python object 
    Usually, pickle is used to make a file for each object, 
     but here, I'm trying to use the append mode of writing a file to store a sequence 
    """ 

    def validate(self, obj): 
     """ 
     Returns whether or not obj is the right Pythonic object 
     """ 
     return True 

    def add(self, obj): 
     if self.validate(obj): 
      with open(FILEPATH, mode='ba') as f: # appending, not writing 
       f.write(pickle.dumps(obj)) 
     else: 
      raise "Did not validate" 

    def unpack(self): 
     """ 
     Go through each line in the file and put each python object 
     into a list, which is returned 
     """ 
     lst = [] 
     with open(FILEPATH, mode='br') as f: 
      # problem must be here, does it not step through the file? 
      for l in f: 
       lst.append(pickle.loads(l)) 
     return lst 

現在,當我運行它,它只能打印出傳遞到類的第一個對象。

if __name__ == '__main__': 

    L = HistoryFile() 
    L.add('a') 
    L.add('dfsdfs') 
    L.add(['dfdkfjdf', 'errree', 'cvcvcxvx']) 

    print(L.unpack())  # only prints the first item, 'a'! 

這是因爲它看到早期的EOF嗎?也許追加僅用於ascii? (在這種情況下,爲什麼讓我做mode ='ba'?)有沒有更簡單的方法來做到這一點?

+0

我不知道泡菜模塊和我的蟒蛇I/O是一個有點生疏,但我的猜測是,你或許讀取來自線文件,而對象存儲沒有換行符分隔(事實上,可能包含換行符,因此如果是這種情況,您可能需要更改它) – falstro 2010-05-18 14:08:26

回答

6

爲什麼你認爲附加二元酸菜會產生一個泡菜? Pickling可以讓你逐一放置(並取回)幾個項目,所以顯然它必須是一個「自我終止」序列化格式。忘記線路,然後讓他們回來!例如:

>>> import pickle 
>>> import cStringIO 
>>> s = cStringIO.StringIO() 
>>> pickle.dump(23, s) 
>>> pickle.dump(45, s) 
>>> s.seek(0) 
>>> pickle.load(s) 
23 
>>> pickle.load(s) 
45 
>>> pickle.load(s) 
Traceback (most recent call last): 
    ... 
EOFError 
>>> 

剛剛趕上EOFError告訴你,你完成取儲存時。

+0

是的,但類必須打開文件以獲得寫入權限,這會擦除文件。我想保留它。這就是爲什麼我想附加文件。在開始寫作之前,閱讀內容的標準做法是什麼? – brainysmurf 2010-05-18 16:44:25

+0

@Adam,只需用'r +'(或更好的'r + b')打開,這樣你就可以使用pickle.HIGHEST_PROTOCOL協議來進行拾取!),cfr http://docs.python.org/library /functions.html?highlight=open#open和http://docs.python.org/library/pickle.html?highlight=pickle#pickle.HIGHEST_PROTOCOL。 – 2010-05-18 17:32:18

+0

@亞歷得到它;謝謝。在公開的例行公事中,我沒有給予足夠的關注。真的很簡單。仍然不確定什麼使用HIGHEST_PROTOCOL雖然,在python3他們推薦協議3,這是默認情況下。 ... – brainysmurf 2010-05-19 02:30:33

3

答案是它可以工作,但是如果沒有'+'in模式,openlines的附加功能會自動添加新行,並將二進制與字符串數據(確定的否定)混合在一起。改變這一行:

with open(FILEPATH, mode='ab') as f: # appending, not writing 
    f.write(pickle.dumps(obj)) 

with open(FILEPATH, mode='a+b') as f: # appending, not writing 
    pickle.dump(obj, f) 

亞歷克斯還指出,更加靈活的使用模式= 'R + B',但這需要適當的追求。由於我想創建一個歷史文件,其行爲類似於先入先出的pythonic對象序列,所以對我來說,嘗試在文件中追加對象實際上是有意義的。我只是沒有做正確的:)

有沒有必要通過該文件,因爲(duh!)它是序列化的。所以更換:

for l in f: 
    lst.append(pickle.loads(l)) 

while 1: 
    try: 
     lst.append(pickle.load(f)) 
    except IOError: 
     break