How to pickle complex enum values in Python

enums, pickle, python

Solution

Don't use a custom class as the enum values; there is no need here. Your specific example doesn't need a separate class at all, you could just use:

class Colors(Enum):
    GREEN = 1
    BLUE = 2

    def __str__(self):
        return self.name

    @property
    def counter(self):
        return self.value

This has better `str()` and `.counter` behaviour; your code requires `str()` to be applied to `Color.<name>.value` rather than directly to `Color.<name>`.

For other custom methods and attributes, put those directly on the `Enum` subclass and they'll be part of the enum members too. If you need more values per entry, set a tuple and pull that tuple apart in a `__init__` method. The documentation has an excellent Planet example that illustrates this further.

Demo:

>>> Colors.BLUE
<Colors.BLUE: 2>
>>> Colors.BLUE.value
2
>>> Colors.BLUE.counter
2
>>> str(Colors.BLUE)
'BLUE'
>>> Colors.BLUE is loads(dumps(Colors.BLUE))
True

Problem

When I try to unpickle pickled complex enum instance, I always get "ValueError: BLUE is not a valid Colors". Is there any way how to pickle and unpickle? ``` from pickle import loads, dumps from enum import Enum class ColorType(object): def __init__(self, counter, name): self.counter = counter self.name = name def __str__(self): return self.name class Colors(Enum): GREEN = ColorType(1, 'GREEN') BLUE = ColorType(2, 'BLUE') color = Colors.BLUE print(color is loads(dumps(color))) ``` I am using Python 2.7.

Original source