Стабильная сериализация Python (например, нет проблем с перемещением модуля pickle) - PullRequest
0 голосов
/ 25 августа 2009

Я рассматриваю использование Количества для определения числа вместе с его единицей. Скорее всего, это значение нужно будет сохранить на диске. Как вы, вероятно, знаете, у травления есть одна важная проблема: если вы перемещаете модуль вокруг, удаление не сможет разрешить класс, и вы не сможете извлечь информацию. Есть обходные пути для этого поведения, но они, действительно, обходные пути.

Решение, которое я придумал для этой проблемы, состояло бы в том, чтобы создать строку, кодирующую уникально данную единицу. Как только вы получите эту кодировку с диска, вы передадите ее заводскому методу в модуле Quantities, который декодирует его в соответствующий экземпляр модуля. Преимущество состоит в том, что даже если вы переместите модуль, все будет работать, если вы передадите маркер магической строки фабричному методу.

Это известная концепция?

1 Ответ

1 голос
/ 25 августа 2009

Похоже на применение Первого принципа Уилера, «все проблемы в информатике могут быть решены с помощью другого уровня косвенности» (второй принцип добавляет «но это обычно создает другую проблему» ;-). По сути, вам нужно косвенное указание для определения типа - сущность внутри типа будет в порядке с подходами, подобными маринованию (вы можете изучить источники pickle.py и copy_reg.py для всех мелкие детали последнего).

В частности, я считаю, что вы хотите сделать это подкласс pickle.Pickler и переопределить метод save_inst. Где текущая версия говорит:

    if self.bin:
        save(cls)
        for arg in args:
            save(arg)
        write(OBJ)
    else:
        for arg in args:
            save(arg)
        write(INST + cls.__module__ + '\n' + cls.__name__ + '\n')

вы хотите написать что-то иное, чем просто модуль и имя класса - какой-то уникальный идентификатор (составленный из двух строк) для класса, вероятно, хранящийся в вашем собственном реестре или реестрах; и аналогично для save_global метода.

Это даже проще для вашего подкласса Unpickler, потому что часть _instantiate уже выделена в своем собственном методе: вам нужно только переопределить find_class, то есть:

def find_class(self, module, name):
    # Subclasses may override this
    __import__(module)
    mod = sys.modules[module]
    klass = getattr(mod, name)
    return klass

он должен взять две строки и вернуть объект класса; Вы можете сделать это через свои реестры, снова.

Как и всегда, когда речь идет о реестрах, вам нужно подумать о том, как обеспечить регистрацию всех объектов (классов), представляющих интерес, и т. Д. И т. Д. Одна из популярных стратегий здесь - не использовать маринование в одиночку, но обеспечить, чтобы все перемещения классов переименования модулей и т. д. записываются где-то постоянно; таким образом, только распаковщик с подклассами может делать всю работу, и он может наиболее удобно делать все это в переопределенном find_class - минуя все вопросы регистрации. Я полагаю, вы считаете это «обходным путем», но мне кажется, что это просто чрезвычайно простая, мощная и удобная реализация концепции «еще одного уровня косвенности», которая позволяет избежать проблемы «еще одной проблемы»; -).

...