Когда объект Python может быть маринован

Я выполняю параллельную обработку в Python с использованием модуля многопроцессорности. Я знаю, что некоторые объекты МОГУТ рассориться (таким образом, передаются как аргументы в multi-p), а другие не могут. Например.

class abc():
    pass

a=abc()
pickle.dumps(a)
'ccopy_reg\n_reconstructor\np1\n(c__main__\nabc\np2\nc__builtin__\nobject\np3\nNtRp4\n.'

Но у меня есть несколько более крупных классов в моем коде (десяток методов или около того), и это происходит:

a=myBigClass()
pickle.dumps(a)
Traceback (innermost last):
 File "<stdin>", line 1, in <module>
 File "/usr/apps/Python279/python-2.7.9-rhel5-x86_64/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle file objects

Это не файл-объект, но в других случаях я получаю другие сообщения, которые говорят в основном: "Я не могу разгадать это".

Так что же такое правило? Количество байтов? Глубина иерархии? Фаза луны?

Ответ 1

Я автор dill. Там довольно полный список того, что соленые огурцы и что не является частью dill. Он может быть запущен на версию python 2.5-3.4 и настроен на то, что рассолы с dill или какие рассолы с pickle, изменив один флаг.

Смотрите здесь: https://github.com/uqfoundation/dill/blob/master/tests/test_objects.py а также https://github.com/uqfoundation/dill/blob/master/dill/_objects.py.

Корень правил для рассолов (с верхней части головы):

  • Можете ли вы зафиксировать состояние объекта по ссылке (т.е. функция, определенная в __main__ по сравнению с импортированной функцией)? [Затем, да]
  • Существует ли общее правило __get_state__ __set_state__ для данного типа объекта? [Затем, да]
  • Зависит ли он от объекта Frame (т.е. полагается на GIL и глобальный стек выполнения)? Итераторы теперь являются исключением из этого: "переигрывание" итератора при рассыпании. [Тогда, нет]
  • Указывает ли экземпляр объекта неправильный путь класса (т.е. из-за того, что он определен в замыкании, в C-привязках или другом __init__ Путь манипуляции)? [Тогда, нет]
  • Это считается опасным для python, чтобы это разрешить? [Тогда, нет]

Итак, (5) сейчас менее распространено, чем раньше, но все еще имеет некоторые длительные эффекты в языке для pickle. dill, по большей части, удаляет (1), (2) и (5) - но по-прежнему справедливо действует (3) и (4).

Я мог бы забыть что-то еще, но я думаю, что в целом это основные правила.

Некоторые модули, такие как multiprocessing, регистрируют некоторые объекты, которые важны для их функционирования. dill регистрирует большинство объектов на языке.

Требуется dill fork multiprocessing, потому что multiprocessing использует cPickle, а dill может только увеличить реестр чистого питона. Вы могли бы, если бы у вас было терпение, пройти через все соответствующие функции copy_reg в dill и применить их к модулю cPickle, и вы получите гораздо больше возможностей multiprocessing. Я нашел простой способ (читать: один лайнер), чтобы сделать это для pickle, но не cPickle.

Ответ 2

Из docs:

Можно мариновать следующие типы:

  • Нет, True и False
  • целые числа, длинные целые числа, числа с плавающей запятой, комплексные числа
  • нормальные и Unicode строки
  • кортежи, списки, наборы и словари, содержащие только выделяемые объекты
  • функции, определенные на верхнем уровне модуля
    • встроенные функции, определенные на верхнем уровне модуля
  • которые определены на верхнем уровне модуля
  • экземпляры таких классов, чей dict или результат вызова getstate() выбирается (см. раздел Протокол pickle для деталей).

Попытки рассортировать непривычные объекты повысят PicklingError исключение; когда это произойдет, неопределенное количество байтов может иметь уже записаны в основной файл. Пытаясь мариновать рекурсивная структура данных может превышать максимальную глубину рекурсии, a RuntimeError будет поднят в этом случае. Вы можете осторожно поднять это ограничение с помощью sys.setrecursionlimit().

Ответ 3

В дополнение к ответу на icedtrees, также выходящему прямо из docs, вы можете настроить и контролировать, как экземпляры экземпляров маринуются и распечатываются, используя специальные методы: object.__getnewargs_ex__(), object.__getnewargs__(), object.__getstate__(), object.__setstate__(state)

Ответ 4

Общее правило заключается в том, что "логические" объекты могут быть маринованными, но "ресурсные" объекты (файлы, блокировки) не могут, потому что нет смысла сохранять/клонировать их.