Стабильная сериализация Python (например.нет проблем с перемещением модуля рассола)

StackOverflow https://stackoverflow.com/questions/1328581

  •  19-09-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

Похоже на применение Первого принципа Уиллера: «все проблемы в информатике могут быть решены с помощью другого уровня косвенности» (Второй принцип добавляет: «но это обычно создает еще одну проблему» ;-).По сути, вам нужно косвенно идентифицировать тип -- тип сущности подойдет для подходов, подобных травлению (вы можете изучить источники 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 -- обход всех вопросов регистрации.Я так понимаю, вы считаете это «обходным решением», но мне это кажется просто чрезвычайно простой, мощной и удобной реализацией концепции «еще одного уровня косвенности», которая позволяет избежать проблемы «еще одной проблемы» ;-).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top