|
| 1 | +# Soubory |
| 2 | + |
| 3 | +Dnes se podíváme na to, jak v Pythonu číst z |
| 4 | +(a pak i zapisovat do) souborů. |
| 5 | + |
| 6 | +Vytvoř si v editoru soubor `basnicka.txt` a napiš do něj libovolnou básničku. |
| 7 | +Soubor ulož. |
| 8 | + |
| 9 | +> [note] |
| 10 | +> Na uložení souboru s básničkou doporučuji použít |
| 11 | +> stejný editor, jaký používáš na Pythonní programy. |
| 12 | +> |
| 13 | +> Používáš-li jiný editor než Atom, dej si při ukládání pozor na kódování: |
| 14 | +> * Nabízí-li ti editor při ukládání výběr kódování, vyber UTF-8. |
| 15 | +> * Je-li k dispozici kódování „UTF-8 bez BOM”, použij to. |
| 16 | +> * Pokud musíš použít Notepad, který výše uvedené možnosti nemá, pak v kódu |
| 17 | +> níže použij místo `'utf-8'` nestandardní `'utf-8-sig'`. |
| 18 | +> |
| 19 | +> Ono [`utf-8`] je název standardního kódování. |
| 20 | +> Zajišťuje, že se případné emoji nebo znaky s diakritikou do souboru uloží |
| 21 | +> tak, aby se daly přečíst i na jiném počítači či operačním systému. |
| 22 | +> 🎉 |
| 23 | +
|
| 24 | +[`utf-8`]: https://en.wikipedia.org/wiki/UTF-8 |
| 25 | + |
| 26 | +Potom napiš tento program: |
| 27 | + |
| 28 | +```python |
| 29 | +soubor = open('basnicka.txt', encoding='utf-8') |
| 30 | +obsah = soubor.read() |
| 31 | +soubor.close() |
| 32 | + |
| 33 | +print(obsah) |
| 34 | +``` |
| 35 | +a spusť ho z adresáře, ve kterém je |
| 36 | +`basnicka.txt` (jinými slovy, aktuální adresář musí být ten, který |
| 37 | +obsahuje soubor s básničkou). |
| 38 | + |
| 39 | +Obsah souboru se vypíše! |
| 40 | + |
| 41 | +Co se tu děje? |
| 42 | +Tak jako `int()` vrací čísla a `input()` řetězce, funkce |
| 43 | +`open()` vrací hodnotu, která představuje *otevřený soubor*. |
| 44 | +Tahle hodnota má vlastní metody. |
| 45 | +Tady používáme metodu `read()`, která |
| 46 | +najednou přečte celý obsah souboru a vrátí ho jako řetězec. |
| 47 | +Nakonec metoda `close()` otevřený soubor zase zavře. |
| 48 | + |
| 49 | + |
| 50 | +## Automatické zavírání souborů |
| 51 | + |
| 52 | +Soubory se dají přirovnat k ledničce: abys něco |
| 53 | +mohl{{a}} z ledničky vzít, nebo dát dovnitř, musíš |
| 54 | +ji předtím otevřít a potom zavřít. |
| 55 | +Bez zavření to sice na první pohled funguje taky, |
| 56 | +ale pravděpodobně potom brzo něco zplesniví. |
| 57 | + |
| 58 | +Stejně tak je docela důležité soubor zavřít po tom, |
| 59 | +co s ním přestaneš pracovat. |
| 60 | +Bez zavření to na první pohled funguje, ale složitější programy se můžou dostat |
| 61 | +do problémů. |
| 62 | +Operační systémy mají limity na počet |
| 63 | +současně otevřených souborů, které se nezavíráním |
| 64 | +dají snadno překročit. |
| 65 | +Na Windows navíc nemůžeš soubor, který je stále |
| 66 | +otevřený, otevřít znovu. |
| 67 | + |
| 68 | +Na korektní zavření souboru ale programátoři často zapomenou. |
| 69 | +Proto Python poskytuje příkaz `with`, který soubory zavírá automaticky. |
| 70 | +Používá se takhle: |
| 71 | + |
| 72 | +```python |
| 73 | +with open('basnicka.txt', encoding='utf-8') as soubor: |
| 74 | + obsah = soubor.read() |
| 75 | + |
| 76 | +print(obsah) |
| 77 | +``` |
| 78 | + |
| 79 | +Příkaz `with` vezme otevřený soubor (který vrací funkce `open`) |
| 80 | +a přiřadí ho do proměnné `soubor`. |
| 81 | +Pak následuje odsazený blok kódu, kde se souborem můžeš pracovat – v tomhle |
| 82 | +případě pomocí metody `read` přečíst obsah jako řetězec. |
| 83 | +Když se Python dostane na konec odsazeného bloku, soubor automaticky zavře. |
| 84 | + |
| 85 | +V naprosté většině případů je pro otevírání souborů nejlepší použít `with`. |
| 86 | + |
| 87 | + |
| 88 | +## Iterace nad soubory |
| 89 | + |
| 90 | +Otevřené soubory se, jako např. řetězce či `range`, |
| 91 | +dají použít s příkazem `for`. |
| 92 | +Tak jako `for i in range` poskytuje za sebou jdoucí čísla a `for c in 'abcd'` |
| 93 | +poskytuje jednotlivé znaky řetězce, `for radek in soubor` bude do proměnné |
| 94 | +`radek` dávat jednotlivé řádky čtené ze souboru. |
| 95 | + |
| 96 | +Například můžeš básničku odsadit, |
| 97 | +aby se vyjímala v textu: |
| 98 | + |
| 99 | +```python |
| 100 | +print('Slyšela jsem tuto básničku:') |
| 101 | +print() |
| 102 | + |
| 103 | +with open('basnicka.txt', encoding='utf-8') as soubor: |
| 104 | + for radek in soubor: |
| 105 | + print(' ' + radek) |
| 106 | + |
| 107 | +print() |
| 108 | +print('Jak se ti líbí?') |
| 109 | +``` |
| 110 | + |
| 111 | + |
| 112 | +Když to zkusíš, zjistíš, že trochu nesedí |
| 113 | +řádkování. Zkusíš vysvětlit, proč tomu tak je? |
| 114 | + |
| 115 | +{% filter solution %} |
| 116 | +Každý řádek končí znakem nového řádku, `'\n'`, |
| 117 | +který možná znáš ze [sekce o řetězcích](../str/). |
| 118 | +Při procházení souboru Python tento znak nechává na konci řetězce `radek` ¹. |
| 119 | +Funkce `print` pak přidá další nový řádek, protože ta na konci |
| 120 | +výpisu vždycky odřádkovává – pokud nedostane argument `end=''`. |
| 121 | + |
| 122 | +--- |
| 123 | + |
| 124 | +¹ Proč to dělá? Kdyby `'\n'` na konci řádků nebylo, |
| 125 | +nedalo by se např. dobře rozlišit, jestli poslední řádek |
| 126 | +končí na `'\n'` |
| 127 | + |
| 128 | +{% endfilter %} |
| 129 | + |
| 130 | +Ideální způsob, jak odřádkování spravit, je odstranit z konce řetězce |
| 131 | +bílé znaky (mezery a nové řádky) pomocí metody `rstrip`: |
| 132 | + |
| 133 | + |
| 134 | +```python |
| 135 | +print('Slyšela jsem tuto básničku:') |
| 136 | +print() |
| 137 | + |
| 138 | +with open('basnicka.txt', encoding='utf-8') as soubor: |
| 139 | + for radek in soubor: |
| 140 | + radek = radek.rstrip() |
| 141 | + print(' ' + radek) |
| 142 | + |
| 143 | +print() |
| 144 | +print('Jak se ti líbí?') |
| 145 | +``` |
| 146 | + |
| 147 | + |
| 148 | +## Psaní souborů |
| 149 | + |
| 150 | +> [warning] Pozor! |
| 151 | +> Pro Python není problém smazat obsah jakéhokoli souboru. |
| 152 | +> Psaní do souborů si zkoušej v adresáři, ve kterém nemáš uložené |
| 153 | +> důležité informace! |
| 154 | +
|
| 155 | +Soubory se v Pythonu dají i zapisovat. |
| 156 | +Pro zápis soubor otevři s pojmenovaným |
| 157 | +argumentem `mode='w'` (z angl. *mode*, mód a *write*, psát). |
| 158 | + |
| 159 | +Pokud soubor už existuje, otevřením s `mode='w'` se veškerý jeho obsah smaže. |
| 160 | +Po zavření tak v souboru bude jen to, co do něj ve svém programu zapíšeš. |
| 161 | + |
| 162 | +Informace pak do souboru zapiš známou funkcí `print`, |
| 163 | +a to s pojmenovaným argumentem `file`: |
| 164 | + |
| 165 | +```python |
| 166 | +with open('druha-basnicka.txt', mode='w', encoding='utf-8') as soubor: |
| 167 | + print('Naše staré hodiny', file=soubor) |
| 168 | + print('Bijí', 2+2, 'hodiny', file=soubor) |
| 169 | +``` |
0 commit comments