Python Language
plank
Zoeken…
Invoering
Shelve is een python-module die wordt gebruikt om objecten in een bestand op te slaan. De plankmodule implementeert permanente opslag voor willekeurige Python-objecten die kunnen worden ingelegd met behulp van een woordenboekachtige API. De plankmodule kan worden gebruikt als een eenvoudige permanente opslagoptie voor Python-objecten wanneer een relationele database overkill heeft. De plank is toegankelijk met sleutels, net als met een woordenboek. De waarden worden ingelegd en geschreven in een database die is gemaakt en beheerd door anydbm.
Opmerkingen
Opmerking: vertrouw er niet op dat het schap automatisch wordt gesloten; roep altijd close()
expliciet aan als je het niet meer nodig hebt, of gebruik shelve.open()
als contextmanager:
with shelve.open('spam') as db:
db['eggs'] = 'eggs'
Waarschuwing:
Omdat de shelve
wordt ondersteund door pickle
, is het onzeker om een plank van een niet-vertrouwde bron te laden. Net als bij augurk kan het laden van een plank willekeurige code uitvoeren.
beperkingen
1 . De keuze van welk databasepakket zal worden gebruikt (zoals dbm.ndbm of dbm.gnu) hangt af van welke interface beschikbaar is. Daarom is het niet veilig om de database rechtstreeks met dbm te openen. De database is ook (helaas) onderworpen aan de beperkingen van dbm, als deze wordt gebruikt - dit betekent dat (de ingelegde weergave van) de objecten die in de database zijn opgeslagen vrij klein moeten zijn, en in zeldzame gevallen kunnen belangrijke botsingen ertoe leiden dat de database updates weigeren.
2. De plankmodule biedt geen ondersteuning voor gelijktijdige lees- / schrijftoegang tot objecten in de plank. (Meerdere gelijktijdige lees-toegangen zijn veilig.) Wanneer een programma een open vak heeft om te schrijven, mag geen ander programma het open hebben om te lezen of te schrijven. Unix-bestandsvergrendeling kan worden gebruikt om dit op te lossen, maar dit verschilt tussen Unix-versies en vereist kennis over de gebruikte database-implementatie.
Voorbeeldcode voor plank
Om een object op te schorten, importeert u eerst de module en wijst u vervolgens de objectwaarde als volgt toe:
import shelve
database = shelve.open(filename.suffix)
object = Object()
database['key'] = object
Om de interface samen te vatten (sleutel is een string, data is een willekeurig object):
import shelve
d = shelve.open(filename) # open -- file may get suffix added by low-level
# library
d[key] = data # store data at key (overwrites old data if
# using an existing key)
data = d[key] # retrieve a COPY of data at key (raise KeyError
# if no such key)
del d[key] # delete data stored at key (raises KeyError
# if no such key)
flag = key in d # true if the key exists
klist = list(d.keys()) # a list of all existing keys (slow!)
# as d was opened WITHOUT writeback=True, beware:
d['xx'] = [0, 1, 2] # this works as expected, but...
d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!
# having opened d without writeback=True, you need to code carefully:
temp = d['xx'] # extracts the copy
temp.append(5) # mutates the copy
d['xx'] = temp # stores the copy right back, to persist it
# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.
d.close() # close it
Een nieuwe plank maken
De eenvoudigste manier om plank te gebruiken is via de klasse DbfilenameShelf . Het gebruikt anydbm om de gegevens op te slaan. U kunt de klasse direct gebruiken of gewoon shelve.open () aanroepen:
import shelve
s = shelve.open('test_shelf.db')
try:
s['key1'] = { 'int': 10, 'float':9.5, 'string':'Sample data' }
finally:
s.close()
Om de gegevens opnieuw te openen, opent u de plank en gebruikt u deze als een woordenboek:
import shelve
s = shelve.open('test_shelf.db')
try:
existing = s['key1']
finally:
s.close()
print existing
Als u beide voorbeeldscripts uitvoert, ziet u:
$ python shelve_create.py
$ python shelve_existing.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
De dbm- module biedt geen ondersteuning voor meerdere toepassingen die tegelijkertijd naar dezelfde database schrijven. Als u weet dat uw klant de plank niet zal wijzigen, kunt u shelve vertellen de database alleen-lezen te openen.
import shelve
s = shelve.open('test_shelf.db', flag='r')
try:
existing = s['key1']
finally:
s.close()
print existing
Als uw programma de database probeert te wijzigen terwijl deze alleen-lezen is geopend, wordt een uitzondering voor toegangsfouten gegenereerd. Het uitzonderingstype is afhankelijk van de databasemodule die door anydbm is geselecteerd toen de database werd gemaakt.
Terugschrijven
Planken volgen standaard geen wijzigingen aan vluchtige objecten. Dat betekent dat als u de inhoud van een artikel in het schap wijzigt, u het schap expliciet moet bijwerken door het artikel opnieuw op te slaan.
import shelve
s = shelve.open('test_shelf.db')
try:
print s['key1']
s['key1']['new_value'] = 'this was not here before'
finally:
s.close()
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
finally:
s.close()
In dit voorbeeld wordt het woordenboek bij 'key1' niet opnieuw opgeslagen, dus wanneer de plank opnieuw wordt geopend, zijn de wijzigingen niet bewaard.
$ python shelve_create.py
$ python shelve_withoutwriteback.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
Als u automatisch wijzigingen in vluchtige objecten wilt opslaan die in de plank zijn opgeslagen, opent u de plank met terugschrijven ingeschakeld. De terugschrijfvlag zorgt ervoor dat de plank alle objecten onthoudt die uit de database zijn opgehaald met behulp van een geheugencache. Elk cache-object wordt ook teruggeschreven naar de database wanneer de plank wordt gesloten.
import shelve
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
s['key1']['new_value'] = 'this was not here before'
print s['key1']
finally:
s.close()
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
finally:
s.close()
Hoewel het de kans op programmeerfouten verkleint en objectpersistentie transparanter kan maken, is het gebruik van de terugschrijfmodus mogelijk niet in elke situatie wenselijk. De cache verbruikt extra geheugen terwijl de plank open is en het kan extra tijd kosten om elk in de cache opgeslagen object terug te schrijven naar de database wanneer het is gesloten. Aangezien er geen manier is om te zien of de objecten in de cache zijn gewijzigd, worden ze allemaal teruggeschreven. Als uw toepassing gegevens meer leest dan het schrijft, voegt writeback meer overhead toe dan u misschien wilt.
$ python shelve_create.py
$ python shelve_writeback.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}