Рассол Python не один-к-одному: разные соленья дают один и тот же объект

1

Может кто-нибудь объяснить это?

pickle.loads(b'\x80\x03X\x01\x00\x00\x00.q\x00h\x00\x86q\x01.') == pickle.loads(b'\x80\x03X\x01\x00\x00\x00.q\x00X\x01\x00\x00\x00.q\x01\x86q\x02.')
>>>True

pickle.loads(b'\x80\x03X\x01\x00\x00\x00.q\x00h\x00\x86q\x01.')
>>>('.', '.')
pickle.loads(b'\x80\x03X\x01\x00\x00\x00.q\x00X\x01\x00\x00\x00.q\x01\x86q\x02.')
>>>('.', '.')

Кажется, что длинная и короткая маринованная версия кортежей с одним и тем же элементом неоднократно.

Другие примеры:

pickle.loads(b'\x80\x03X\x01\x00\x00\x00#q\x00X\x01\x00\x00\x00#q\x01\x86q\x02.')
>>>('#', '#')
pickle.loads(b'\x80\x03X\x01\x00\x00\x00#q\x00h\x00\x86q\x01.')
>>>('#', '#')

pickle.loads(b'\x80\x03X\x01\x00\x00\x00$q\x00X\x01\x00\x00\x00$q\x01\x86q\x02.')
>>>('$', '$')
pickle.loads(b'\x80\x03X\x01\x00\x00\x00$q\x00h\x00\x86q\x01.')
>>>('$', '$')

Я пытаюсь индексировать предметы по их маринуру, но я не нахожу предметы, потому что их соленые огурцы, похоже, меняются.

Я использую Python 3.3.2 на Ubuntu.

  • 0
    Обратите внимание на pickle.dumps('.', 3) == b'\x80\x03X\x01\x00\x00\x00.q\x00.' и последовательность X\x01\x00\x00\x00. встречается дважды в более длинном маринованном варианте ('.','.') и только один раз в коротком. Поэтому, хотя я не читаю формат Pickle, я думаю, что у вас есть один файл Pickle, который указывает на кортеж, содержащий одну и ту же строку дважды, и другой, который указывает на кортеж, содержащий две строки, которые оказались равными. Использование коротких строк в реализации Python может стереть эту разницу во время распечатывания, но даже если они не выглядят одинаково при печати и равны.
  • 1
    Рассмотрим широко эквивалентный вопрос, который кто-то может задать: «Я индексирую объекты по их представлению JSON, но [1, 1] и [ 1, 1 ] - это разные представления JSON одного и того же объекта». JSON - довольно простой формат, и канонизировать его довольно просто: сделайте пробел регулярным, закажите ключи в словарях, вот и все. Форматы pickle менее просты, и для типов в целом вам будет сложно определить и ввести одинаковые значения. Вы можете использовать набор для хранения канонической версии всего, что можно хэшировать, но не все, что можно рассортировать, можно хэшировать.
Показать ещё 3 комментария
Теги:
serialization
pickle

1 ответ

3
Лучший ответ

Соленые огурцы не уникальны; формат рассола на самом деле является крошечным небольшим языком программирования, а разные программы (соленые огурцы) могут создавать один и тот же результат (незакрашенный объект). Из документов:

Поскольку формат данных рассола на самом деле представляет собой крошечный язык программирования, ориентированный на стек, и в кодировании определенных объектов принимается некоторая свобода, возможно, что два модуля [pickle и cPickle] создают разные потоки данных для одного и того же входа объекты. Однако гарантируется, что они всегда смогут читать потоки данных друг друга.

Там даже функция pickletools.optimize, которая будет принимать рассол и выводит лучший рассол. Вам нужно будет перепроектировать вашу программу.

  • 1
    Как вы превращаете объекты в канонические индексы?
  • 1
    @mtanti: зависит от вашего варианта использования. Вам может не понадобиться, или вы можете использовать id , или repr может быть уместным, или вы можете написать собственный код.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню