Когда объект 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
Общее правило заключается в том, что "логические" объекты могут быть маринованными, но "ресурсные" объекты (файлы, блокировки) не могут, потому что нет смысла сохранять/клонировать их.