📁 Práce se soubory a výjimky

Sešit v šuplíku

O čem to je

Hraješ hru, nasbíráš 500 bodů a vypneš počítač. Kdyby si program pamatoval body jen v proměnných, po vypnutí by zmizely. Proměnné žijí jen v operační paměti, dokud program běží. Aby se data zachovala, musí je program zapsat do souboru na disk.

Práce se soubory je jako práce se sešitem v šuplíku: otevřeš ho, čteš nebo píšeš a zase ho zavřeš. A když sešit v šuplíku není, nesmí se program zhroutit. Proto k souborům patří i výjimky.

Nové pojmy

SouborPojmenovaná data uložená na disku. Zůstanou tam i po vypnutí programu a počítače. Textový soubor obsahuje řádky textu.body.txt, zaci.csv
Otevření souboru open()Funkce, která soubor zpřístupní programu. Má jméno souboru, režim a kódování.open("body.txt", "r", encoding="utf-8")
Režim otevřeníŘíká, co se souborem chceš dělat. "r" čtení (výchozí), "w" zápis (starý obsah smaže!), "a" připsání na konec.Deník, do kterého jen přidáváš, otevři s "a".
Blok withOtevře soubor a po skončení odsazeného bloku ho sám zavře, i když nastane chyba. Je to doporučený způsob práce se soubory.with open("body.txt", encoding="utf-8") as f:
Kódování (encoding)Pravidlo, jak se znaky ukládají do bajtů. Pro češtinu používej "utf-8", jinak se mohou rozbít písmena s háčky a čárkami.encoding="utf-8"

Zápis a čtení

  • with open("zaci.txt", "w", encoding="utf-8") as f:
  •     f.write("Eva\n")
  •     f.write("Petr\n")
  •  
  • with open("zaci.txt", "r", encoding="utf-8") as f:
  •     for radek in f:
  •         print(radek.strip())
První blok otevře soubor pro zápis. Když neexistuje, vytvoří ho.
write zapíše text. Nový řádek nepřidá sám, proto \n na konci.
Na konci bloku with se soubor zavře a data jsou na disku.
Druhý blok soubor otevře pro čtení a cyklem projde řádky.
Každý řádek končí znakem \n. strip() ho odstraní, aby print nevypsal prázdné řádky navíc.
MetodaCo vrátí
f.read()celý obsah jako jeden řetězec
f.readline()jeden další řádek
f.readlines()seznam všech řádků
for radek in f:prochází řádky jeden po druhém
Do souboru denik.txt chceš každý den připsat nový řádek a nesmazat staré. Jaký režim?
Režim "a" (append): with open("denik.txt", "a", encoding="utf-8") as f: → f.write("Dnes pršelo\n"). Režim "w" by celý deník smazal.
Soubor cisla.txt má na každém řádku jedno číslo. Sečti je.
s = 0, pak with open("cisla.txt", encoding="utf-8") as f: → for r in f: → s = s + int(r). Z řádku je text, proto int(). (Znak \n na konci int() toleruje.)
✗Otevřu soubor s výsledky v režimu "w", abych do něj přidal nový výsledek.
✓Pro přidání použij "a".

Režim "w" soubor při otevření vyprázdní. Všechny staré výsledky by zmizely.

Data přežijí konec programu jen v souboru. Soubor otevírej přes with open(jmeno, režim, encoding="utf-8"), který ho sám zavře. "r" čte, "w" přepisuje, "a" připisuje.

Když něco selže

O čem to je

Program se zeptá na věk a uživatel napíše „sedmnáct“. Nebo program chce otevřít soubor, který někdo smazal. Bez ošetření program spadne a vypíše červenou chybu. Uživatel přijde o rozdělanou práci.

Dobrý program s chybami počítá. Chybu zachytí, vysvětlí ji uživateli a pokračuje. K tomu slouží výjimky a blok try/except.

Nové pojmy

Výjimka (exception)Chyba, která nastane za běhu programu. Python přeruší provádění a vytvoří objekt výjimky s jejím druhem a popisem. Když ji nikdo nezachytí, program skončí.int("abc") vyvolá výjimku ValueError.
Ošetření výjimky try / exceptKód, který může selhat, dáš do bloku try. Když v něm nastane výjimka, Python skočí do bloku except a program pokračuje dál.try: x = int(vstup) → except ValueError: print("To není číslo")
else a finallyBlok else se provede, když v try žádná výjimka nenastala. Blok finally se provede vždy, s chybou i bez ní. Hodí se na úklid.Ve finally se zavírá spojení nebo vypisuje „Konec“.
SouborData uložená na disku, otevírají se funkcí open(). Když soubor pro čtení neexistuje, vznikne výjimka FileNotFoundError.open("neni.txt")

Nejčastější výjimky

VýjimkaKdy nastanePříklad
ValueErrorhodnota má správný typ, ale nesmyslný obsahint("abc")
ZeroDivisionErrordělení nulou10 / 0
FileNotFoundErrorsoubor neexistujeopen("neni.txt")
IndexErrorindex mimo seznam[1, 2][5]
KeyErrorklíč není ve slovníku{}["a"]
TypeErroroperace s nevhodným typem"a" + 1

Bezpečné načtení čísla

  • while True:
  •     try:
  •         vek = int(input("Věk: "))
  •         break
  •     except ValueError:
  •         print("Zadej celé číslo.")
  • print("Za rok ti bude", vek + 1)

Když uživatel napíše „sedmnáct“, int() vyvolá ValueError. Řádek break se přeskočí, program vypíše radu a ptá se znovu. Když napíše „17“, převod se povede a break ukončí cyklus.

Pořadí bloků

try: kód, který může selhat.
except Druh: co dělat, když nastane výjimka daného druhu. Bloků except může být víc.
else: co dělat, když vše proběhlo bez chyby (nepovinné).
finally: co se provede vždy (nepovinné).
Co vypíše f(0)? Funkce: try: r = 10 / x → except ZeroDivisionError: print("nulou ne") → else: print("ok") → finally: print("konec").
Dělení nulou vyvolá výjimku, provede se except: nulou ne. else se přeskočí. finally se provede vždy: konec.
Načti soubor nastaveni.txt, a když neexistuje, použij výchozí nastavení.
try: → with open("nastaveni.txt", encoding="utf-8") as f: text = f.read() → except FileNotFoundError: → text = "výchozí". Program nespadne a pokračuje.
✗try: … a except: pass kolem celého programu, aby nikdy nespadl.
✓Zachytávej jen konkrétní výjimky, které čekáš (except ValueError:), a uživateli řekni, co se stalo.

Holé except s pass schová i chyby v tvém kódu. Program pak tiše dělá nesmysly a chybu nenajdeš.

Výjimka je chyba za běhu programu. Kód, který může selhat, dej do try a konkrétní výjimku zachyť v except. else běží bez chyby, finally vždy.