Если травление было прервано, обязательно ли травление обязательно завершится неудачей? - питон - PullRequest
4 голосов
/ 31 октября 2009

Предположим, моя попытка записать объект консервирования на диск не завершена из-за сбоя. Будет ли попытка открепления объекта всегда приводить к исключению или возможно, что выписанный фрагмент может быть интерпретирован как допустимый рассол, и ошибка останется незамеченной?

Ответы [ 5 ]

7 голосов
/ 31 октября 2009

В отличие от других предложенных ответов, я полагаю, что мы можем привести веские аргументы в пользу извлечения рассола. Этот ответ: «Да, неполный рассол всегда приводит к исключению».

Почему мы можем это сделать? Потому что формат «pickle» на самом деле является небольшим языком, основанным на стеке. На языке стека вы пишете код, который помещает элемент за элементом в стек, а затем вызывает оператор, который что-то делает с накопленными вами данными. И так уж получилось, что рассол должен заканчиваться командой «.», Которая гласит: «возьмите элемент сейчас в нижней части стека и верните его как значение этого рассола». Если ваш рассол рано отрубится, он не закончится этой командой, и вы получите ошибку EOF.

Если вы хотите попытаться восстановить некоторые из данных, вам, возможно, придется написать свой собственный интерпретатор или вызвать где-нибудь в pickle.py запрос о том, чтобы вызвать EOFError, когда завершите интерпретацию стека, не найдя «.». Главное, что нужно иметь в виду, это то, что, как и в большинстве языков, основанных на стеке, большие структуры данных создаются «в обратном направлении»: сначала вы помещаете в стек множество маленьких строк или чисел, , а затем . операция, которая говорит «собрать их вместе в список» или «собрать пары элементов в стек и создать словарь». Таким образом, если прерывание будет прервано, вы обнаружите, что стек полон кусков объекта, который должен был быть построен, но вам не хватит того финального кода, который сообщит вам , что будет построен из кусочков.

2 голосов
/ 31 октября 2009

Это развитие ответа С. Лотта с моим предложением: добавьте хеш или контрольную сумму к вашим данным, которые вы проверяете перед повторной очисткой.

Вот (простая) реализация safepickle / safeunpickle, чтобы показать, как вы можете дополнить данные с хэшем (криптографически сильный хеш в данном случае):

import hashlib
import cPickle as pickle

_HASHLEN = 20

def safepickle(obj):
    s = pickle.dumps(obj)
    s += hashlib.sha1(s).digest()
    return s

def safeunpickle(pstr):
    data, checksum = pstr[:-_HASHLEN], pstr[-_HASHLEN:]
    if hashlib.sha1(data).digest() != checksum:
        raise ValueError("Pickle hash does not match!")
    return pickle.loads(data)


l = range(20)
p = safepickle(l)
new_l = safeunpickle(p)
print new_l == l

Этот метод гарантирует, что то, что вы извлекаете, соответствует тому, что вы засолили и записали на диск ранее, но, конечно, не защищает от смешивания разных засолок или злонамеренных атак.

(Этот метод можно обобщить для шаблона safe_write_file и safe_read_file для любых данных всего файла.)

2 голосов
/ 31 октября 2009

Выбор объекта возвращает объект str или записывает объект str в файл ... он не изменяет исходный объект. Если во время вызова с травлением произойдет «сбой» (исключение), результат не будет возвращен вызывающей стороне, поэтому у вас нет ничего, что можно было бы попытаться распечатать. Кроме того, с какой стати вы захотите убрать грязный мусор, оставшийся после исключения?

1 голос
/ 31 октября 2009

Чтобы быть уверенным, что у вас есть «полный» файл засолки, вам нужно засолить три вещи.

  1. Выберите какой-либо заголовок, в котором указано, сколько объектов и как будет выглядеть флаг конца файла. Например, кортеж целого числа и строки EOF.

  2. Рассолите предметы, которые вам действительно нужны. Количество определяется заголовком.

  3. Выберите объект хвоста, который вас на самом деле не интересует, но который просто соответствует заявлению, сделанному в заголовке. Это может быть просто строка, которая соответствует заголовку.

Когда вы распаковываете этот файл, вы должны распаковать три вещи:

  1. Заголовок. Вы заботитесь о количестве и форме хвоста.

  2. Объекты, которые вас действительно волнуют.

  3. Хвостовой объект. Убедитесь, что он соответствует заголовку. Кроме этого, он не передает ничего, кроме того, что файл был написан целиком.

1 голос
/ 31 октября 2009

Я сомневаюсь, что вы могли бы заявить, что это всегда приведет к исключению. Pickles - это программы, написанные на специализированном языке стека. Внутренние детали солений меняются от версии к версии, и иногда добавляются новые протоколы солений. Состояние маринада после сбоя и последующее воздействие на отстойник было бы очень сложно обобщить в простом утверждении типа «это всегда приведет к исключению».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...