2012-01-23 6 views
12

Я с удивлением обнаружил, что python (версия 3.2.2) отказывается рассортировать объект, потому что его dict содержал ссылку на Ellipsis. Из других built-in constants рассол счастлив работать с False, True и None, как указано в pickle documentation, но также дроссели на NotImplemented.Почему нельзя использовать эллипсис и NotImplemented?

Python 3.2.2 (default, Sep 5 2011, 21:17:14) 
[GCC 4.6.1] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import pickle 
>>> pickle.dumps(True) 
b'\x80\x03\x88.' 
>>> pickle.dumps(False) 
b'\x80\x03\x89.' 
>>> pickle.dumps(None) 
b'\x80\x03N.' 
>>> pickle.dumps(Ellipsis) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
_pickle.PicklingError: Can't pickle <class 'ellipsis'>: attribute lookup builtins.ellipsis failed 
>>> pickle.dumps(NotImplemented) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
_pickle.PicklingError: Can't pickle <class 'NotImplementedType'>: attribute lookup builtins.NotImplementedType failed 

Для полноты из менее полезных встроенных констант, __debug__ просто BOOL, поэтому не вызывает никаких проблем; copyright, license и credits работа (их тип site._Printer); quit и exit нет (их тип site.Quitter, который не может быть найден как определено внутри функции).

Может кто-нибудь объяснить, почему это - наверняка Ellipsis и NotImplemented не просто упустили? Единственная релевантная информация, которую я могу найти, - this bug, которая жалуется, что NoneType (т. Е. type(None)) не подбирается. Один из комментаторов упоминает, что type(Ellipsis) и type(NotImplemented) не могут быть маринованными, по-видимому, не замечая, что их экземпляры тоже не могут быть.

+2

Odd упущение, хотя можно было бы утверждать, что вы на самом деле не должны держать ссылки на те значения, чтобы начать с. – millimoose

+0

@Inderdial: мой конкретный пример использования был в контейнере, который отслеживает фрагменты, к которым был осуществлен доступ. Поскольку ломтики можно мариновать, кажется странным, что Ellipsis (который на самом деле является только особым видом среза) не может. Сохранение ссылки на «NotImplemented», вероятно, менее вероятно, будет полезно, хотя я могу себе представить, что кто-то может захотеть его для какой-то сложной схемы сравнения. – James

+1

@James - Строго говоря, «Эллипсис» не является особым видом среза, но его интерпретация абсолютно определяется пользователем. В Numpy это больше похоже на последовательность из нуля или более секций, определяемую автоматически. –

ответ

1

Цитирование documentation:

Следующие типы могут быть маринованные:

  • None, True, и Ложные
  • целые числа, числа с плавающей запятой, комплексные числа
  • строки, байт , bytearrays
  • кортежи, списки, наборы и словари, содержащие только сортируемые объекты
  • функции, определенные на верхнем уровне модуля
  • встроенные функции, определенной на верхнем уровне модуля
  • классов, которые определены на верхнем уровне модуля
  • экземпляры таких классов, __dict__ или __setstate __() является пригоден для консервирования (см экземпляров раздела травления класса для деталей)

два объекта в вопросе, Ellipsis и NotImplemented, не соответствуют ни одному из этих правил, и, следовательно, не может быть рис KLED.

Я сомневаюсь, что есть какая-то лучшая причина для того, чтобы не включать все встроенные константы в первое правило, отличное от того, что никто не видел необходимости в нем. Если вы действительно думаете, что pickle должен поддерживать это, подумайте о публикации запроса функции (лучше приведите убедительный вариант использования!).

+0

Я видел этот список, но не был уверен, был ли он эксклюзивным. В частности, встроенные функции, такие как 'map' и' open', можно мариновать, но, похоже, не соответствуют ни одному из этих критериев (если вы не считаете их «определенными на верхнем уровне модуля», и в этом случае это кажется странным, что подобные «NoneType» не могут быть маринованными). – James

+2

'map' и' open' определены на верхнем уровне модуля '__builtin__' (попробуйте' import __builtin__ как B; B.map'), 'NoneType' - это встроенный класс, а не функция. Документация кажется мне последовательной! –

+0

Хм, это имеет смысл - спасибо за объяснение (хотя теперь мне интересно, где NoneType определен, если где угодно!). Хотя я действительно хотел знать, что такое рассуждение позади этого поведения - возможно, я должен просто представить отчет об ошибке. – James

4

Нет никаких оснований для того, чтобы python не раскалывал такие вещи, как Ellipsis и NotImplemented, и, честно говоря, не имея их picklable, вносит вклад в хрупкость python как параллельный/асинхронный язык. Вы можете рассортировать эти типы объектов с помощью dill, заменяя pickle.Да, я знаю, что это мягкая напыщенность, но я думаю, что NotImplemented в вашем целевом коде не должен останавливать вас от использования multiprocessing или какого-либо другого из параллельного python ... или сохранения состояния вашего сеанса python для использования позднее ... или что угодно.

Python 3.2.5 (default, May 19 2013, 14:25:55) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill 
>>> dill.dumps(True) 
b'\x80\x03\x88.' 
>>> dill.dumps(False) 
b'\x80\x03\x89.' 
>>> dill.dumps(None) 
b'\x80\x03N.' 
>>> dill.dumps(Ellipsis) 
b'\x80\x03cdill.dill\n_eval_repr\nq\x00X\x08\x00\x00\x00Ellipsisq\x01\x85q\x02Rq\x03.' 
>>> dill.dumps(NotImplemented) 
b'\x80\x03cdill.dill\n_eval_repr\nq\x00X\x0e\x00\x00\x00NotImplementedq\x01\x85q\x02Rq\x03.' 

Получить dill здесь: https://github.com/uqfoundation/dill

+0

Благодарим за это ... это заставило меня посмотреть, и я нашел эту ссылку, которая помогла мне решить мою проблему, распараллеливаясь в IPython: http://nbviewer.ipython.org/gist/anonymous/5241793 – Omegaman

+0

@GB: потрясающе. Это хорошая ссылка, которую вы опубликовали. Я также знаю, что 'dill' используется в качестве замены солености в' multiprocessing', 'mpi4py' и некоторых других пакетах python, используемых в параллельных вычислениях. –

Смежные вопросы