2013-04-28 12 views
7

Po aktualizacji definicji klasy przez rekompilację skryptu, pickle odmawia serializacji wcześniej utworzonych obiektów tej klasy, podając błąd: "Can not pickle object: to nie jest ten sam obiekt co "Python pickle: radzenie sobie ze zaktualizowanymi definicjami klas

Czy istnieje sposób, aby powiedzieć pickle, że powinien zignorować takie przypadki? Aby zidentyfikować klasy według nazwy, zignoruj ​​ten wewnętrzny unikalny identyfikator, który powoduje niezgodność?

Zdecydowanie poproszę, jako odpowiedź na sugestię alternatywnego, równoważnego modułu, który rozwiązuje ten problem w wygodny i solidny sposób.


Dla porównania, oto moja motywacja:

tworzę wysoką wydajność, szybki rozwój iteracja środowisko, w którym skrypty Pythona są edytowane na żywo. Skrypty są wielokrotnie rekompilowane, ale dane pozostają w kompilacjach. W ramach celów wydajności staram się używać pikle do serializacji, aby uniknąć kosztu pisania i aktualizowania kodu serializacji jawnej dla stale zmieniających się struktur danych.

Przeważnie klasyfikuję typy wbudowane. Uważam, aby unikać znaczących zmian w klasach, które wybieram, i kiedy to konieczne, używam mechanizmu copy_reg.pickle do przeprowadzenia konwersji na unpickle.

Rekompilacja skryptów uniemożliwia mi w ogóle trawienie obiektów, nawet jeśli definicje klas nie uległy zmianie (lub zmieniły się tylko w łagodny sposób).

+1

Nie spędziłem z tym wiele czasu, ale może to być przydatne: http://docs.python.org/2/library/pickle.html#pickling-and-unpickling-normal-class-includes – mgilson

Odpowiedz

0

dwa rozwiązania przychodzą do mojego umysłu:

  1. przed marynowane można ustawić object.__class__

    >>> class X(object): 
        pass 
    
    >>> class Y(object): 
        pass 
    
    >>> x = X() 
    >>> x.__class__ = Y 
    >>> type(x) 
    <class '__main__.Y'> 
    

    Być może używać persistent_id do tego, ponieważ każdy obiekt jest przekazywana do niego.

  2. zdefiniuj __reduce__, aby wykonać dokładnie to samo, co pikle. (Przyjrzeć się pickle.py do tego)

6

ile można rozpakować wcześniejszą wersję definicji klasy, marynata odniesienia musi zrzucić i załadować instancja jest teraz zniknął. To jest "niemożliwe".

Jeśli jednak chcesz to zrobić, możesz zapisać poprzednich wersji definicji klas ... i wtedy po prostu musisz oszukać pikling w odniesieniu do swojej starej/zapisanej klasy definicje, a nie używanie najbardziej aktualnych - które mogą oznaczać tylko edycję obj.__class__ lub obj.__module__, aby wskazywały na twoją starą klasę. W twojej instancji klasy mogą też występować inne dziwne rzeczy, które również odnoszą się do starej definicji klasy, z którą musiałbyś sobie poradzić. Ponadto, jeśli dodasz lub usuniesz metodę klasy, możesz natknąć się na nieoczekiwane wyniki lub odpowiednio zaktualizować instancję. Kolejną interesującą nowością jest to, że możesz sprawić, by osoba rozpusta zawsze używała najnowszej wersji twojej klasy.

Mój pakiet do serializacji, dill, ma kilka metod, które mogą zrzucać skompilowane źródło z obiektu Live Code do pliku tymczasowego, a następnie serializować za pomocą tego pliku tymczasowego. To jedna z nowszych części pakietu, więc nie jest tak solidna jak reszta koperku.Co więcej, twój przypadek użycia nie jest przypadkiem użycia, który bym rozważał, ale mogłem zobaczyć, jak byłoby to przyjemne.

+0

Ok , Dodałem tę funkcję do kopa w najnowszej wersji github. Wdrożone z mniejszą ilością oszustów, niż myślałem ... po prostu serializuj definicję klasy z marynatą i voila. –

Powiązane problemy