Nauč se Python > Kurzy > Začátečnický kurz > Spolupráce a Open-Source > Soubory

Soubory

Dnes se podíváme na to, jak v Pythonu číst z (a pak i zapisovat do) souborů.

Ke čtení textu ze souboru jsou potřeba tři kroky:

Vytvoř si v editoru soubor basnicka.txt a napiš do něj libovolnou básničku. Soubor ulož.

Na uložení souboru s básničkou doporučuji použít stejný editor, jaký používáš na Pythonní programy.

Používáš-li jiný editor než Atom, dej si při ukládání pozor na kódování:

  • Nabízí-li ti editor při ukládání výběr kódování, vyber UTF-8.
  • Je-li k dispozici kódování „UTF-8 bez BOM”, použij to.
  • Pokud musíš použít Notepad, pak v kódu níže použij místo 'utf-8' nestandardní 'utf-8-sig'.

Potom napiš tento program:

soubor = open('basnicka.txt', encoding='utf-8')
obsah = soubor.read()
print(obsah)
soubor.close()

a spusť ho z adresáře, ve kterém je basnicka.txt (jinými slovy, aktuální adresář musí být ten, který obsahuje soubor s básničkou).

Obsah souboru se vypíše!

Co se tu děje? Tak jako int() vrací čísla a input() řetězce, funkce open() vrací hodnotu, která představuje otevřený soubor. Tahle hodnota má vlastní metody. Tady používáme metodu read(), která najednou přečte celý obsah souboru a vrátí ho jako řetězec. Na metodu close(), která otevřený soubor zavírá, se podíváme později.

Iterace nad soubory

Otevřené soubory se, jako např. řetězce či range, dají použít s příkazem for. Tak jako for i in range poskytuje za sebou jdoucí čísla a for c in 'abcd' poskytuje jednotlivé znaky řetězce, for radek in soubor bude do proměnné radek dávat jednotlivé řádky čtené ze souboru.

Například můžeme básničku odsadit, aby se vyjímala v textu:

print('Slyšela jsem tuto básničku:')
print()
soubor = open('basnicka.txt', encoding='utf-8')
for radek in soubor:
    print('    ' + radek)
soubor.close()
print()
print('Jak se ti líbí?')

Když to zkusíš, zjistíš, že trochu nesedí řádkování. Zkusíš vysvětlit, proč tomu tak je?

Řešení

Zavírání souborů

Je docela důležité soubor potom, co s ním přestaneš pracovat, zavřít (pomocí metody close()). Operační systémy mají limity na počet současně otevřených souborů, které se nezavíráním dají snadno překročit. Na Windows navíc nemůžeš soubor, který je stále otevřený, otevřít znovu.

Soubory se dají přirovnat k ledničce: abychom něco mohly z ledničky vzít, nebo dát dovnitř, musíme ji napřed otevřít a nakonec zavřít. Bez zavření to sice na první pohled funguje taky, ale pravděpodobně potom brzo něco zplesniví.

Zapomenout zavřít soubor je docela jednoduché: například pokud by v rámci zpracování souboru nastala výjimka nebo kdybys vyskočila z funkce pomocí return, náš předchozí kód by close nezavolal, a soubor by zůstal otevřený.

K tomu, abychom soubor nezapomněli v podobných příkazech zavřít, slouží příkaz try/finally, který jsme si ukázali v souvislosti s výjimkami.

Pro připomenutí, finally se provede vždycky – i když blok try skončí normálně, i když v něm nastane výjimka, i když z něj „vyskočíš” pomocí return či break.

def iniciala():
    """Vrátí první písmeno v daném souboru."""

    soubor = open('basnicka.txt', encoding='utf-8')
    try:
        obsah = soubor.read()
        return obsah[0]
    finally:
        soubor.close()

print(iniciala())

Blok finally se takhle dá použít vždycky, když je potřeba něco ukončit nebo zavřít – ať už je to soubor, nebo třeba připojení k databázi.

Příkaz with

Protože je try/finally celkem dlouhé a nepohodlné, má Python i příjemnější variantu, příkaz with:

def iniciala():
    """Vrátí první písmeno v daném souboru."""

    with open('basnicka.txt', encoding='utf-8') as soubor:
        obsah = soubor.read()
        return obsah[0]

print(iniciala())

Tenhle příkaz jsme už viděli u testování, kde uvozoval blok, ve kterém má nastat výjimka – potom, co blok skončí, se zkontroluje, jestli nastala a jestli je toho správného typu. V našem případě se po skončení bloku zavře soubor, ať už výjimka nastala nebo ne. Podobně jako s finally se zavře vždycky – ať už blok with skončil normálně, výjimkou, nebo, jako tady, „vyskočením” ven.

V naprosté většině příkazů je pro práci se soubory nejlepší použít with.

Psaní souborů

Soubory se v Pythonu dají i zapisovat. Pro zápis se soubor otevře pomocí pojmenovaného argumentu mode='w' (z angl. mode, mód a write, psát). Zapisovat jednotlivé řetězce se pak dá metodou write.

Pozor na to, že pokud soubor už existuje, otevřením pro zápis ho bez milosti přepíšeš.

A taky nezapomeň ukončovat řádky – metoda write to za tebe neudělá, '\n' je potřeba přidávat „ručně“.

with open('basnicka.txt', mode='w', encoding='utf-8') as soubor:
    soubor.write('Naše staré hodiny\n')
    soubor.write('Bijí čtyři hodiny\n')

Případně se dá použít funkce print, která kromě do terminálu umí, pomocí pojmenovaného argumentu file, vypisovat i do otevřeného souboru. Ostatní možnosti printu – automatické odřádkování, převádnění na řetězce, možnost vypsat víc hodnot najednou apod. – samozřejmě zůstávají.

with open('basnicka.txt', mode='w', encoding='utf-8') as soubor:
    print('Naše staré hodiny', file=soubor)
    print('Bijí', 2+2, 'hodiny', file=soubor)