2010-05-18 3 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

ответ

6

Почему вы считаете, что придуманные бинарные соленые огурцы будут давать единственный маринад ?! Травление позволяет добавлять (и возвращать) несколько элементов один за другим, поэтому, очевидно, это должен быть «самозавершающийся» формат сериализации. Забудьте о линиях и просто верните их! Например:

>>> 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, чтобы сказать вам, когда вы закончите unpickling.

+0

Да, но класс должен открыть файл для разрешения на запись, который удаляет файл , Я хочу сохранить его. Вот почему я думал о добавлении файла. Итак, стандартная практика читать в содержании перед открытием для написания? – brainysmurf

+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. –

+0

@Alex получил его; Благодарю. Я не уделял достаточно пристального внимания + в открытой рутине. На самом деле довольно просто. Все еще не уверен, что использовать HIGHEST_PROTOCOL, хотя в python3 они рекомендуют протокол 3, который по умолчанию по умолчанию. ... – brainysmurf

3

Ответ заключается в том, что он работает, но без режима «+» новые строки, автоматически добавленные функцией добавления функции open, смешивают двоичный файл со строковыми данными (определенный нет-нет). Измените эту строку:

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) 

Алекс также указывает на то, что для более режима использования гибкости = «г + Ь», но это требует соответствующего искание. Так как я хотел создать файл истории, который вел себя как первая, последняя из последовательности pythonic-объектов, для меня действительно было целесообразно попробовать добавить объекты в файл. Я просто делал это неправильно :)

Нет необходимости проходить через файл, потому что (duh!) Он сериализуется. Так заменить:

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

с

while 1: 
    try: 
     lst.append(pickle.load(f)) 
    except IOError: 
     break 
Смежные вопросы