Lekce 4 - Uložení objektů do CSV v Pythonu
V minulé lekci, Práce s textovými soubory v Pythonu, jsme si ukázali zápis do textových souborů i jejich čtení.
Aplikace z minula byla jednoduchá a spíše učebnicová. Udělejme si nyní opravdovou databázi uživatelů pomocí textových souborů. Ukládat budeme samozřejmě objekty, čili si program snadno předěláte na databázi upomínek v diáři, databázi nejlepších výsledků ve hře, databázi zvířat v chovné stanici nebo na cokoli, co budete potřebovat evidovat.
Formát CSV
Nebudeme vymýšlet žádný složitý způsob ukládání dat do textových souborů, protože již jeden osvědčený a standardní existuje. Jmenuje se CSV (jako Comma Separated Values), tedy hodnoty oddělené čárkou, případně středníkem.
Pojďme se shodnout na tom, jak bude třída uživatele vypadat. Následně
si ukážeme, jak její instance do CSV uložíme. Vytvoříme si nový soubor
main.py
. Do něj si vložíme třídu Uzivatel
. U
uživatele budeme evidovat jeho jméno, věk a datum, kdy byl registrován.
Konstruktor bude instanci inicializovat na základě těchto 3 vlastností.
Přepíšeme si metodu __str__()
tak, aby vrátila jméno
uživatele. Třída tedy bude vypadat takto:
class Uzivatel(): def __init__(self, jmeno, vek, registrovan): self.jmeno = jmeno self.vek = vek self.registrovan = registrovan def __str__(self): return self.jmeno
Pojďme si ukázat, jak budou uživatelé ve formátu CSV vypadat. Každý řádek bude reprezentovat jednoho uživatele. Vlastnosti uživatele budou odděleny středníky. Uživatel Pavel Slavík, kterému je 22 let a zaregistroval se 21.3.2000 by vypadal takto:
Pavel Slavík;22;21.3.2000
Na první pohled vidíme, že je soubor relativně jednoduše čitelný, i
když nezasvěcený se může jen domnívat, co je číslo 22
a k
čemu se váže ono datum.
V souboru může být samozřejmě více uživatelů, tedy více řádků.
Třídu uživatele máme, protože však ctíme objektový návrh,
vytvoříme si i třídu pro naši databázi. Ta bude obsahovat kolekci
uživatelů, tvořenou seznamem. Přidávání uživatelů (případně jejich
mazání, vyhledávání a podobně) bude realizováno metodami. Databáze bude
konečně obsahovat metody k načtení CSV souboru a také k uložení obsahu
databáze do souboru. Jméno souboru bude další atribut databáze. Přidejme
si tedy k projektu další třídu Databaze
a napišme její
kostru:
class Databaze(): uzivatele = [] def __init__(self, soubor): pass def pridejUzivatele(self, jmeno, vek, registrovan): pass def vratVsechny(self): pass def uloz(self): pass def nacti(self): pass
Pojďme postupně naimplementovat jednotlivé metody. Začněme konstruktorem.
V konstruktoru si uložíme cestu k databázovému souboru:
def __init__(self, soubor): self.soubor = soubor
To bylo velmi jednoduché a i na další metodě není co vymýšlet:
def pridejUzivatele(self, jmeno, vek, registrovan):
u = Uzivatel(jmeno, vek, registrovan)
self.uzivatele.append(u)
Metoda vratVsechny()
nám vrátí všechny uživatele. Podobně
můžeme v budoucnu udělat metody pro vyhledávání jen některých
uživatelů. Uživatele navrátíme ve formě pole:
def vratVsechny(self): return self.uzivatele
Uložení uživatelů do CSV
Nyní se konečně dostáváme k práci s CSV souborem. Začneme
with
blokem a instancí file handleru získanou funkcí
open()
. Uvnitř proiterujeme náš seznam uživatelů a pro
každého uživatele vytvoříme pole stringů z jeho vlastností. Nestringové
vlastnosti musíme na string explicitně převést. Pole poté spojíme na
dlouhý string, ve kterém budou položky oddělené středníky. Spojení za
nás vykoná metoda join()
. Ta se na rozdíl od metody
split()
volá přímo na řetězci (oddělovači) a jako parametr
přijímá jednotlivé položky na spojení. Pusťme se do toho:
def uloz(self): with open(self.soubor, "w", encoding="utf-8") as f: for u in self.uzivatele: hodnoty = [u.jmeno, str(u.vek), u.registrovan.strftime("%d.%m.%Y")] radek = ";".join(hodnoty) f.write(radek + "\n")
Všimněte si, že datum registraci před uložením do souboru naformátujeme na "den.měsíc.rok".
Aplikace
Naše aplikace bude formulářová pomocí knihovny tkinter
.
Pokud preferujete raději PyQt,
bude pro vás díky její jednoduchosti hračka ji i pro tuto knihovnu
upravit.
Do main.py
si vložme poslední třídu, reprezentující okno
aplikace:
class Aplikace(tkinter.Frame): def __init__(self, master): super().__init__(master=master) self.master = master self.pack() self.db = Databaze("uzivatele.csv") self.master.title("Lekce4") self.tlacitkoUlozit = tkinter.Button(self.master, text="Uložit", width=40, command=self.tlacitkoUlozitClicked) self.tlacitkoUlozit.pack(fill=tkinter.X) def tlacitkoUlozitClicked(self): pass root = tkinter.Tk() aplikace = Aplikace(root) root.mainloop()
V kódu vytváříme atribut db
, do kterého v konstruktoru
uložíme novou instanci naší databáze. Do aplikace přidáváme také nové
tlačítko a nastavujeme automaticky velikost formuláře metodou
pack()
. Metodu tlacitkoUlozitClicked()
jsme
zaregistrovali, aby se zavolala po kliknutí na tlačítko.
Zbytek kódu mimo třídu Aplikace
se stará o vytvoření okna
po spuštění programu. Tkinter je případně detailně vysvětlen v článku
Úvod
do tkinteru v Pythonu.

V jeho Click handleru (naše metoda tlacitkoUlozitClicked()
)
přidáme do databáze 2 uživatele. Bude to nyní pro vyzkoušení, později
bude aplikace vypadat lépe. Dále celou databázi uložíme do souboru.
def tlacitkoUlozitClicked(self): self.db.pridejUzivatele("Pavel Slavík", 22, datetime.datetime(2000, 3, 21)) self.db.pridejUzivatele("Jan Novák", 31, datetime.datetime(2012, 10, 30)) self.db.uloz()
Aplikaci spustíme. Poté otevřeme (např. v NotePadu) soubor
uzivatele.csv
, který se v její složce vytvořil, a vidíme, že
má následující obsah:
Pavel Slavík;22;21.3.2000 Jan Novák;31;30.10.2012
Vše tedy funguje, jak má
V další lekci, Uložení objektů do CSV v Pythonu část 2, načteme do aplikace uživatele.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 291x (1.26 kB)
Aplikace je včetně zdrojových kódů v jazyce Python