Пикировка array.array в версии 2.4 с использованием cPickle

Я работаю над проектом, построенным на python 2.4 (это встроенный проект python, поэтому у меня нет выбора используемой версии python). Во всем приложении мы используем array.array для хранения данных.

Поддержка травления объектов array.array была добавлена ​​в picklecPickle) в версии 2.5. У нас есть жизнеспособный обходной путь в 2.4 при использовании класса pickle на чистом Python (мы создаем подкласс Pickler/Unpickler для обработки массивов), но он не работает с cPickle (нам это нужно из-за проблем с производительностью).

Какие-либо предложения?

ИЗМЕНИТЬ — РЕШЕНИЕ:

Это окончательный код, который, кажется, работает (спасибо за предложения):

# Add serialization for array objects
def array_unpickler(data):
    return array.array(data[0], data[1:])
def array_pickler(arr):
    return array_unpickler, ("%s%s" % (arr.typecode, arr.tostring()),)
copy_reg.pickle(array.ArrayType, array_pickler, array_unpickler)

person Paul Osborne    schedule 25.02.2010    source источник


Ответы (3)


Вы можете использовать модуль стандартной библиотеки copy_reg, чтобы зарегистрировать функции для работы с травление экземпляров типов, изначально не поддерживающих травление; cPickle будет использовать ваши зарегистрированные функции там, где это необходимо. Я бы применил именно этот «крючковый» подход к вашему требованию травления экземпляров array.array.

person Alex Martelli    schedule 25.02.2010
comment
Превосходно! У меня это работает. Ваше предложение привело меня к effbot.org/librarybook/copy-reg.htm , который дает пару отличных примеров. - person Paul Osborne; 26.02.2010

Я не уверен, можно ли расширить тип массива с помощью метода __reduce__ (возможно, с помощью подкласса), но вы всегда можете попробовать преобразовать свои массивы в последовательности и обратно... если встроенный механизм расширения не будет работать для тебя. (хак)

Я не пробовал это раньше, но вы можете попробовать добавить поддержку через copy_reg... по сути тот же результат, что и реализация __reduce__ в вашем собственном классе или подклассе, но немного чище.

person pestilence669    schedule 25.02.2010
comment
Для массивов я бы преобразовал их в большой строковый объект с .tostring(), который является просто копией байтов в памяти, представляющих массив. - person Joe Koberg; 26.02.2010
comment
При таком подходе вы также захотите включить код типа массива. Я пробовал этот подход, но столкнулся с проблемами, связанными с получением состояния кода типа в незавершенном объекте. Я пытался понять __initargs__ без особого успеха... Думаю, я выберу подход copy_req. - person Paul Osborne; 26.02.2010

Вроде бы можно замариновать, а вот результат не замаринуешь

Python 2.4.5 (#2, Jan 21 2010, 20:05:55) 
[GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cPickle as pickle
>>> import array
>>> a=array.array('i','12345678')
>>> pickle.dumps(a,2)
'\x80\x02carray\narray\nq\x01)\x81q\x02.'
>>> b=pickle.loads(_)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: array() takes at least 1 argument (0 given)

Похоже, дампы даже не содержат информации о коде типа ... или даже данных :(

>>> a=array.array('c','abcdefghijkl') 
>>> pickle.dumps(a,2)                                                                                                                                                                             
'\x80\x02carray\narray\nq\x01)\x81q\x02.'
>>> 
person John La Rooy    schedule 25.02.2010
comment
Да, похоже, это подтверждает эту ошибку из списка рассылки python: mail.python.org/pipermail/python-bugs-list/2006-January/ Смарт был добавлен в 2.5 - person Paul Osborne; 26.02.2010