Teď se podívejme na to, jak v Pythonu číst ze souborů (a pak i jak do nich zapisovat).
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, dej si při ukládání pozor na kódování:
'utf-8'
nestandardní 'utf-8-sig'
.Ono utf-8
je název standardního kódování.
Zajišťuje, že se případné emoji nebo znaky s diakritikou do souboru uloží
tak, aby se daly přečíst i na jiném počítači či operačním systému.
Potom napiš tento program:
soubor = open('basnicka.txt', encoding='utf-8')
obsah = soubor.read()
soubor.close()
print(obsah)
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áš metodu read()
, která
najednou přečte celý obsah souboru a vrátí ho jako řetězec.
Nakonec metoda close()
otevřený soubor zase zavře.
Soubory se dají přirovnat k ledničce: abys něco mohla z ledničky vzít, nebo dát dovnitř, musíš ji předtím otevřít a potom zavřít. Bez zavření to sice na první pohled funguje taky, ale pravděpodobně potom brzo něco zplesniví.
Stejně tak je docela důležité zavířít soubor – ideálně hned po tom, co s ním přestaneš pracovat. Bez zavření to na první pohled funguje, ale složitější programy se můžou dostat do problémů. 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.
Na korektní zavření souboru ale programátoři často zapomenou.
Proto Python poskytuje příkaz with
, který soubory zavírá automaticky.
Používá se takhle:
with open('basnicka.txt', encoding='utf-8') as soubor:
obsah = soubor.read()
print(obsah)
Příkaz with
vezme otevřený soubor (který vrací funkce open
)
a přiřadí ho do proměnné za as
(tady soubor
).
Pak následuje odsazený blok kódu, kde se souborem můžeš pracovat – v tomhle
případě pomocí metody read
přečíst obsah jako řetězec.
Když se Python dostane na konec odsazeného bloku, soubor automaticky zavře.
V naprosté většině případů je pro otevírání souborů nejlepší použít with
.
Otevřené soubory jsou iterovatelné – dají se, stejně jako např. řetězce či
range
, použít s příkazem for
.
Tak jako for i in range(...)
poskytuje za sebou jdoucí čísla a
for znak in 'abcd'
poskytuje jednotlivé znaky řetězce, for radek in soubor
bude v proměnné radek
poskytovat jednotlivé řádky čtené ze souboru.
Aby se básnička líp vyjímala v textu, pojďme ji odsadit – před každý řádek dát měkolik mezer:
print('Slyšela jsem tuto básničku:')
print()
with open('basnicka.txt', encoding='utf-8') as soubor:
for radek in soubor:
print(' ' + radek)
print()
print('Jak se ti líbí?')
Když to zkusíš, zjistíš, že trochu nesedí řádkování. Zkusíš se zamyslet, proč tomu tak je?
Ideální způsob, jak odřádkování spravit, je odstranit z konce řetězce
bílé znaky (mezery a nové řádky) pomocí metody rstrip
:
print('Slyšela jsem tuto básničku:')
print()
with open('basnicka.txt', encoding='utf-8') as soubor:
for radek in soubor:
radek = radek.rstrip()
print(' ' + radek)
print()
print('Jak se ti líbí?')
Pozor!
Pro Python není problém smazat obsah jakéhokoli souboru. Psaní do souborů si zkoušej v adresáři, ve kterém nemáš uložené důležité informace!
Soubory se v Pythonu dají i zapisovat.
Pro zápis soubor otevři s pojmenovaným
argumentem mode='w'
(z angl. mode, mód a write, psát).
Pokud soubor už existuje, otevřením s mode='w'
se veškerý jeho obsah smaže.
Po zavření tak v souboru bude jen to, co do něj ve svém programu zapíšeš.
Informace pak do souboru zapiš známou funkcí print
,
ale s pojmenovaným argumentem file
:
with open('druha-basnicka.txt', mode='w', encoding='utf-8') as soubor:
print('Naše staré hodiny', file=soubor)
print('Bijí', 2+2, 'hodiny', file=soubor)
Čteš-li tyto materiály poprvé, tuto sekci můžeš s klidným svědomím přeskočit. Pokročilejším ale doporučuju vsadit věci do širšího kontextu.
Příkaz with
pracuje s tzv. kontextem (tady s kontextem otevřeného
souboru), který má začátek a konec a při ukončení je potřeba něco udělat
(tady zavřít soubor).
Kontext je v podstatě zkratka pro try
/finally
. Pamatuješ si na finally
?
Toto:
with open('basnicka.txt', encoding='utf-8') as soubor:
# Zpracování souboru
obsah = soubor.read()
je zkratka pro:
soubor = open('basnicka.txt', encoding='utf-8')
try:
# Zpracování souboru
obsah = soubor.read()
finally:
# Ukončení kontextu
soubor.close()
Jak with
tak finally
zaručí, že se soubor vždy uzavře:
když se zpracování povede, ale i když v něm nastane výjimka,
nebo když z něj vyskočíš pomocí return
nebo break
:
def nacti_cele_cislo(jmeno_souboru):
with open(jmeno_souboru, encoding='utf-8') as soubor:
return int(soubor.read())
# I když "return" vyskočí z funkce (nebo int() zbůsobí ValueError),
# soubor se zavře.
# Pro vyzkoušení napiš do souboru 'cislo.txt' nějaké číslo.
print(nacti_cele_cislo('cislo.txt') * 11)