Objecten opslaan en laden en augurk gebruiken

Ik probeer objecten op te slaan en te laden met de module pickle.
Eerst declareer ik mijn objecten:

>>> class Fruits:pass
...
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30

Daarna open ik een bestand met de naam ‘Fruits.obj’ (voorheen heb ik een nieuw .txt-bestand gemaakt en hernoemde ik ‘Fruits.obj’):

>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)

Hierna sluit ik mijn sessie en ik begon een nieuwe en ik plaatste de volgende (proberen toegang te krijgen tot het object dat het zou moeten worden opgeslagen):

file = open("Fruits.obj",'r')
object_file = pickle.load(file)

Maar ik heb dit bericht:

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

Ik weet niet wat ik moet doen omdat ik dit bericht niet begrijp.
Weet iemand hoe ik mijn object ‘banaan’ kan laden?
Bedankt!

BEWERKEN:
Zoals sommigen van jullie hebben gesuggereerd, zeg ik:

>>> import pickle
>>> file = open("Fruits.obj",'rb')

Er waren geen problemen, maar het volgende dat ik zei was:

>>> object_file = pickle.load(file)

En ik heb een fout:

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

Antwoord 1, autoriteit 100%

Wat betreft je tweede probleem:

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

Nadat je de inhoud van het bestand hebt gelezen, staat de bestandsaanwijzer aan het einde van het bestand – er zijn geen verdere gegevens om te lezen. U moet het bestand terugspoelen zodat het opnieuw vanaf het begin wordt gelezen:

file.seek(0)

Wat u echter meestal wilt doen, is een contextmanager gebruiken om het bestand te openen en er gegevens uit te lezen. Op deze manier wordt het bestand automatisch gesloten nadat het blok is uitgevoerd, wat u ook zal helpen uw bestandsbewerkingen in zinvolle brokken te organiseren.

Ten slotte is cPickle een snellere implementatie van de augurkmodule in C. Dus:

In [1]: import _pickle as cPickle
In [2]: d = {"a": 1, "b": 2}
In [4]: with open(r"someobject.pickle", "wb") as output_file:
   ...:     cPickle.dump(d, output_file)
   ...:
# pickle_file will be closed at this point, preventing your from accessing it any further
In [5]: with open(r"someobject.pickle", "rb") as input_file:
   ...:     e = cPickle.load(input_file)
   ...:
In [7]: print e
------> print(e)
{'a': 1, 'b': 2}

Antwoord 2, autoriteit 48%

Het volgende werkt voor mij:

class Fruits: pass
banana = Fruits()
banana.color = 'yellow'
banana.value = 30
import pickle
filehandler = open("Fruits.obj","wb")
pickle.dump(banana,filehandler)
filehandler.close()
file = open("Fruits.obj",'rb')
object_file = pickle.load(file)
file.close()
print(object_file.color, object_file.value, sep=', ')
# yellow, 30

Antwoord 3, autoriteit 39%

Je vergeet het ook als binair te lezen.

In je schrijfgedeelte heb je:

open(b"Fruits.obj","wb") # Note the wb part (Write Binary)

In het leesgedeelte heb je:

file = open("Fruits.obj",'r') # Note the r part, there should be a b too

Dus vervang het door:

file = open("Fruits.obj",'rb')

En het zal werken 🙂


Wat uw tweede fout betreft, deze wordt hoogstwaarschijnlijk veroorzaakt door het niet goed sluiten/synchroniseren van het bestand.

Probeer dit stukje code te schrijven:

>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
>>> filehandler.close()

En dit (ongewijzigd) om te lezen:

>>> import pickle
>>> file = open("Fruits.obj",'rb')
>>> object_file = pickle.load(file)

Een nettere versie zou het withstatement gebruiken.

Voor schrijven:

>>> import pickle
>>> with open('Fruits.obj', 'wb') as fp:
>>>     pickle.dump(banana, fp)

Om te lezen:

>>> import pickle
>>> with open('Fruits.obj', 'rb') as fp:
>>>     banana = pickle.load(fp)

Antwoord 4, autoriteit 17%

Altijd openen in binaire modus, in dit geval

file = open("Fruits.obj",'rb')

Antwoord 5, autoriteit 5%

U kunt anycachegebruiken om het werk voor u te doen. Ervan uitgaande dat je een functie myfunchebt die de instantie maakt:

from anycache import anycache
class Fruits:pass
@anycache(cachedir='/path/to/your/cache')    
def myfunc()
    banana = Fruits()
    banana.color = 'yellow'
    banana.value = 30
return banana

Anycache roept myfuncde eerste keer aan en pikt het resultaat naar een
bestand in cachedirmet een unieke identifier (afhankelijk van de functienaam en de argumenten) als bestandsnaam.
Bij elke opeenvolgende run wordt het gebeitste object geladen.

Als de cachedirbewaard blijft tussen python-runs, wordt het gebeitste object overgenomen uit de vorige python-run.

Er wordt ook rekening gehouden met de functieargumenten.
Een gerefactorde implementatie werkt op dezelfde manier:

from anycache import anycache
class Fruits:pass
@anycache(cachedir='/path/to/your/cache')    
def myfunc(color, value)
    fruit = Fruits()
    fruit.color = color
    fruit.value = value
return fruit

Antwoord 6, autoriteit 4%

Je hebt het bestand niet in binaire modus geopend.

open("Fruits.obj",'rb')

Zou moeten werken.

Voor je tweede fout is het bestand hoogstwaarschijnlijk leeg, wat betekent dat je het per ongeluk hebt geleegd of de verkeerde bestandsnaam hebt gebruikt of zoiets.

(Dit gaat ervan uit dat je je sessie echt hebt afgesloten. Zo niet, dan is dat omdat je het bestand niet hebt afgesloten tussen schrijven en lezen).

Ik heb je code getest en het werkt.


Antwoord 7, autoriteit 3%

Het lijkt erop dat je je klasinstanties over verschillende sessies heen wilt bewaren, en het gebruik van pickleis een goede manier om dit te doen. Er is echter een pakket met de naam Kleptodat het opslaan van objecten abstraheert naar een woordenboekinterface, zodat je kunt kiezen om objecten te picken en ze in een bestand op te slaan (zoals hieronder weergegeven), of de objecten in te pakken en op te slaan ze naar een database, of gebruik in plaats van augurk json, of vele andere opties. Het leuke van Kleptois dat door te abstraheren naar een gemeenschappelijke interface, het het gemakkelijk maakt, zodat u niet de details op laag niveau hoeft te onthouden van hoe u via beitsen naar een bestand of anderszins kunt opslaan .

Merk op dat het werkt voor dynamisch toegevoegde klasseattributen, wat augurk niet kan doen…

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive 
>>> db = file_archive('fruits.txt')
>>> class Fruits: pass
... 
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
>>> 
>>> db['banana'] = banana 
>>> db.dump()
>>> 

Dan herstarten we…

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('fruits.txt')
>>> db.load()
>>> 
>>> db['banana'].color
'yellow'
>>> 

Kleptowerkt op python2 en python3.

Verkrijg de code hier:
https://github.com/uqfoundation

Other episodes