Próbuję zapisywać i ładować obiekty za pomocą pickle
modułu.
Najpierw deklaruję moje obiekty:
>>> class Fruits:pass
...
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
Następnie otwieram plik o nazwie „Fruits.obj” (wcześniej utworzyłem nowy plik .txt i zmieniłem nazwę „Fruits.obj”):
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
Po wykonaniu tej czynności zamykam sesję i rozpoczynam nową i stawiam następną (próbując uzyskać dostęp do obiektu, który ma być zapisany):
file = open("Fruits.obj",'r')
object_file = pickle.load(file)
Ale mam taką wiadomość:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
ValueError: read() from the underlying stream did notreturn bytes
Nie wiem, co robić, ponieważ nie rozumiem tej wiadomości. Czy ktoś wie, jak mogę załadować mój obiekt „banan”? Dziękuję Ci!
EDYCJA: Jak niektórzy z was sugerowali, umieściłem:
>>> import pickle
>>> file = open("Fruits.obj",'rb')
Nie było problemu, ale następny włożyłem to:
>>> object_file = pickle.load(file)
I mam błąd:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
EOFError
Odpowiedzi:
A co do drugiego problemu:
Po przeczytaniu zawartości pliku wskaźnik pliku znajdzie się na końcu pliku - nie będzie już żadnych danych do odczytania. Musisz przewinąć plik do tyłu, aby został ponownie odczytany od początku:
Jednak zazwyczaj chcesz użyć menedżera kontekstu, aby otworzyć plik i odczytać z niego dane. W ten sposób plik zostanie automatycznie zamknięty po zakończeniu wykonywania bloku, co pomoże również zorganizować operacje na plikach w znaczące fragmenty.
Wreszcie, cPickle to szybsza implementacja modułu pikle w C. Więc:
źródło
{"a": 1, "b": 2}
tworzy słownik z kluczami"a"
i"b"
w nim. W dokumentacji online nazywa się to wyrażeniem wyświetlanym w słowniku . To tylko jeden z kilku różnych sposobówdict
konstruowania obiektu typu , który jest jednym z kilku standardowych wbudowanych typów danych dostępnych w Pythonie.pickle
tego, który importujecpickle
automatycznie, jeśli jest to możliwe. docs.python.org/3.1/whatsnew/3.0.html#library-changesU mnie działa:
źródło
class Fruits
definicję, abypickle.load()
móc odtworzyć obiekt z danych zapisanych w pliku binarnym. Najlepszą praktyką w tego typu sytuacjach jest umieszczenieclass Fruits
definicji w oddzielnym pliku .py (czyniąc go niestandardowym modułem), a następnieimport
tego modułu lub elementów z niego w razie potrzeby (tj. W obu sesjach). Na przykład, jeśli umieścisz go w pliku o nazwie,MyDataDefs.py
możesz pisaćfrom MyDataDefs import Fruits
. Daj mi znać, jeśli jest to niejasne, a ja odpowiednio zaktualizuję moją odpowiedź.my_data_defs.py
usingfrom my_data_defs import Fruits
.Zapominasz również czytać to jako binarne.
W swojej części pisemnej masz:
W części do czytania masz:
Więc zamień go na:
I zadziała :)
Jeśli chodzi o drugi błąd, najprawdopodobniej jest to spowodowane nieprawidłowym zamknięciem / synchronizacją pliku.
Spróbuj napisać ten fragment kodu:
A to (bez zmian) do przeczytania:
Bardziej zgrabna wersja użyłaby tego
with
oświadczenia.Do pisania:
Do czytania:
źródło
W tym przypadku zawsze otwieraj w trybie binarnym
źródło
Nie otworzyłeś pliku w trybie binarnym.
Powinno działać.
W przypadku drugiego błędu plik jest najprawdopodobniej pusty, co oznacza, że nieumyślnie go opróżniłeś lub użyłeś złej nazwy pliku lub coś w tym stylu.
(Zakładamy, że naprawdę zamknąłeś sesję. Jeśli nie, to dlatego, że nie zamknąłeś pliku między zapisem a odczytem).
Przetestowałem Twój kod i działa.
źródło
Wygląda na to, że chcesz zapisywać swoje instancje klas między sesjami, a używanie
pickle
to przyzwoity sposób na zrobienie tego. Istnieje jednak pakiet o nazwie,klepto
który abstrahuje zapisywanie obiektów w interfejsie słownika, więc możesz wybrać marynowanie obiektów i zapisywanie ich do pliku (jak pokazano poniżej) lub marynowanie obiektów i zapisywanie ich w bazie danych lub zamiast użyj pickle użyj json lub wielu innych opcji. Zaletąklepto
jest to, że abstrakcja do wspólnego interfejsu ułatwia to, dzięki czemu nie musisz pamiętać niskopoziomowych szczegółów, jak zapisać przez wytrawianie do pliku lub w inny sposób.Zauważ, że działa to dla dynamicznie dodawanych atrybutów klas, których pikle nie mogą zrobić ...
Następnie uruchamiamy ponownie…
Klepto
działa na python2 i python3.Pobierz kod tutaj: https://github.com/uqfoundation
źródło
Możesz użyć anycache, aby wykonać pracę za Ciebie. Zakładając, że masz funkcję,
myfunc
która tworzy instancję:Anycache wywołuje
myfunc
po raz pierwszy i zapisuje wynik do plikucachedir
przy użyciu unikalnego identyfikatora (w zależności od nazwy funkcji i argumentów) jako nazwy pliku. W każdym kolejnym przebiegu marynowany przedmiot jest ładowany.Jeśli
cachedir
zachowany jest między uruchomieniami języka Python, piklowany obiekt jest pobierany z poprzedniego uruchomienia języka Python.Uwzględniane są również argumenty funkcji. Wdrożenie refaktoryzowane działa podobnie:
źródło