[Python] How to pickle my custom enum class without a PicklingError?

Discussão em 'Python' iniciado por Stack, Abril 21, 2025.

  1. Stack

    Stack Membro Participativo

    I have written an Interval python class with attributes for a starting point, an ending point, and a "curve type" that is used to interpolate between the start and the end. I only plan to support a couple specific predefined curve types, so I have put them in an Enum. Each curve type has a few properties, so I have made each enum value a namedtuple. Here is my (simplified) code so you can see what I mean:

    from collections import namedtuple
    from enum import Enum

    class CurveType(namedtuple('CurveType', ['name', 'symbol', 'interp_fn']), Enum):
    LINEAR = 'linear', '\u002F', lambda x: x
    SBEND = 's-bend', '\u23B0', lambda x: x**3 / (x**3 + (1 - x)**3)

    class Interval:
    def __init__(self, start, end, curve_type=None):
    self.start = start
    self.end = end
    self.curve_type = curve_type if curve_type else CurveType.LINEAR

    def __str__(self):
    return f'({self.start} {self.curve_type.symbol} {self.end})'

    def evaluate_at(self, x):
    proportion = (x - self.start) / (self.end - self.start)
    return self.curve_type.interp_fn(proportion)


    This works perfectly adequately for my needs:

    i = Interval(3, 6, CurveType.SBEND)
    print (i)
    print (i.curve_type)
    print (i.evaluate_at(4))


    (3 ⎰ 6)
    CurveType.SBEND
    0.11111111111111105
    ​

    Except that I'd like to be able to pickle an individual Interval instance, and that currently gives me an error:

    import pickle
    with open('interval.pickle', 'ab') as file:
    pickle.dump(i, file)


    Traceback (most recent call last):
    File "/path/to/test.py", line 28, in <module>
    pickle.dump(i, file)
    _pickle.PicklingError: Can't pickle <class '__main__.CurveType'>: it's not the same object as __main__.CurveType
    ​

    I don't totally get what this error message is saying. I keep thinking that I understand it and then confusing myself again.

    Anyhow, how can I accomplish my goals here? I am not married to the exact approach I have shown, so long as I can:

    • create Interval objects
    • give each Interval a CurveType using syntax like curve_type = CurveType.LINEAR
    • specify multiple properties for each CurveType including its interpolation function
    • pickle my Interval objects

    ((I'm currently running Python 3.11 but could upgrade if there's a relevant feature in a newer version.))

    Continue reading...

Compartilhe esta Página