Ga naar hoofdinhoud

Alles bekijken: len en items

Hier bouw je op verder: Door een dictionary lopen

Weet je dit niet meer zeker? Lees het terug voordat je verdergaat.

In Gegevens opslaan met SqliteDict wist je precies welke sleutels er in je database stonden: je had ze zelf getypt. Een server weet dat niet. Daar bepalen de bezoekers wat erin komt, en wil je weten wat er staat, dan moet je kijken. Je oefent nog steeds in losse scripts, met de mijn_data.db uit de vorige les.

Alles bekijken​

Maak bekijk_db.py, naast test_db.py:

from sqlitedict import SqliteDict

with SqliteDict("mijn_data.db") as db:
print(len(db), "sleutels")
for sleutel, waarde in db.items():
print(sleutel, "=", waarde)
  1. Regel 4:

    len(db) telt de sleutels, net als bij een dictionary.

  2. Regel 5-6:

    db.items() geeft elke sleutel met zijn waarde. De lus staat binnen het with-blok, want daarbuiten is de database dicht.

Draai python bekijk_db.py:

2 sleutels
naam = Jan
leeftijd = 16

Heb je in de vorige les meer opgeslagen, zoals een woonplaats, dan staat die er ook bij en telt het een sleutel meer. Bewaar dit script: in de lessen hierna kijk je er steeds mee wat je server heeft opgeslagen. Verander alleen de bestandsnaam tussen de haakjes, bijvoorbeeld in "gastenboek.db".

Test jezelf. In mijn_data.db staan naam en leeftijd. Je draait dit script:

from sqlitedict import SqliteDict

with SqliteDict("mijn_data.db") as db:
db["klas"] = "4B"
Controlevraag
Daarna draai je bekijk_db.py. Wat is de eerste regel die het print?
Kies wat jij denkt. Bij het goede antwoord zie je de uitleg.

Er gaat iets mis​

AttributeError na het with-blok​

AttributeError: 'NoneType' object has no attribute 'select'

Oorzaak: de lus staat na het with-blok, en daar is de database al dicht. db.items() haalt pas iets uit het bestand als je erdoorheen loopt. Zet je paren = db.items() binnen het blok en de lus erbuiten, dan krijg je dus dezelfde fout. Met db.values() gaat het net zo. Vraag je na het blok len(db) of db["naam"], dan eindigt de fout op 'select_one'.

Oplossing: laat de lus inspringen, zodat hij binnen het blok staat. Heb je de paren ook na het blok nodig, maak er dan binnen het blok een lijst van met list().

from sqlitedict import SqliteDict

# FOUT: de lus staat na het with-blok
with SqliteDict("mijn_data.db") as db:
paren = db.items()

for sleutel, waarde in paren:
print(sleutel, "=", waarde)

# GOED: list() haalt alles op zolang de database open is
with SqliteDict("mijn_data.db") as db:
paren = list(db.items())

for sleutel, waarde in paren:
print(sleutel, "=", waarde)

0 sleutels, terwijl je wel iets opsloeg​

0 sleutels

Oorzaak: je draait bekijk_db.py vanuit een andere map. Net als in Gegevens opslaan met SqliteDict maakt SqliteDict daar stil een nieuwe, lege mijn_data.db aan.

Oplossing: start het script vanuit de terminal in je projectmap, en gooi de lege mijn_data.db in de andere map weg.

Opdrachten​

Opdracht 1: Predict - Twee keer kat​

from sqlitedict import SqliteDict

with SqliteDict("dieren.db") as db:
db["kat"] = "miauw"
db["hond"] = "woef"
db["kat"] = "mauw"
db.commit()

with SqliteDict("dieren.db") as db:
print(len(db), "sleutels")
for sleutel, waarde in db.items():
print(sleutel, "=", waarde)
Voorspel
Hoeveel sleutels telt dit, en wat staat er bij kat?
Kies wat jij denkt. Bij het goede antwoord zie je de uitleg.

Opdracht 2: Run​

Maak bekijk_db.py uit deze les en draai het. Zie je dezelfde sleutels als in test_db.py, of meer?

Antwoord

Het kunnen er meer zijn. bekijk_db.py toont alles wat ooit in mijn_data.db is gezet, ook uit een oudere versie van test_db.py. Een database onthoudt wat je opsloeg, niet wat er nu in je script staat.

Opdracht 3: Investigate - De lus naar buiten​

Haal in bekijk_db.py de inspringing weg voor de twee regels van de lus, zodat ze onder het with-blok staan. Draai het. Wat print het nog, en op welke regel stopt het?

Antwoord

Het print nog 2 sleutels, want die regel staat binnen het blok. Daarna stopt het op de regel met for met AttributeError: 'NoneType' object has no attribute 'select': de database is dan al dicht. Zet de inspringing daarna weer terug.

Opdracht 4: Modify - Netjes op een rij​

Laat bekijk_db.py de sleutels op alfabet zetten, en een lege database melden met Database is leeg in plaats van 0 sleutels.

Tip

sorted(db.items()) geeft de paren gesorteerd op sleutel. Een lege database telt in een if als niet waar, net als een lege dictionary.

Antwoord
from sqlitedict import SqliteDict

with SqliteDict("mijn_data.db") as db:
if not db:
print("Database is leeg")
for sleutel, waarde in sorted(db.items()):
print(sleutel, "=", waarde)

Test het lege geval met een bestandsnaam die nog niet bestaat, zoals "leeg.db". SqliteDict maakt dat bestand dan aan, zonder sleutels. Gooi het daarna weg.

Door naar Bestaat de sleutel? in en get.