Často je potřeba provést se souborem nějakou činnost, např. načíst celý obsah souboru do paměti. Jaká je typická podoba kódu, který pro tento účel vídávám u začínajících programátorů v Pythonu a jak to udělat lépe se dozvíte v dnešním příspěvku.
Původní kód
V příspěvku se pro jednoduchost zaměřím pouze na čtení obsahu celého souboru do paměti. Avšak stejný princip, jako ukáži níže, platí samozřejmě pro další operace.
Vezměme si následující kód:
f = open('file.txt') contents = f.read() f.close()
Soubor otevřeme, načteme z něj jeho obsah a uzavřeme jej.
Proč takto raději ne?
Co když kód f.read()
způsobí vyhození výjimky? Pak nedojde k zavolání f.close()
a soubor se uzavře, až když bude objekt f
odstraněn garbage collectorem (toto samozřejmě závisí na implementaci Pythonu). Lze se tomu vyhnout použitím bloku try/finally
:
f = open('file.txt') try: contents = f.read() finally: f.close()
Stále je zde však ono volání f.close()
, na které bychom neměli zapomenout, což se může snadno stát. Navíc je kód méně přehledný, než původní verze.
Jak to udělat lépe?
Od Pythonu 2.5 máme příkaz with
, který se k tomuto úkolu perfektně hodí. Tento příkaz je samozřejmě k dispozici i v Pythonu 3. Kód s jeho využitím bude vypadat následovně:
with open('file.txt') as f: contents = f.read()
Nejdříve se otevře soubor file.txt
. Pokud se otevření podaří, tak dojde k pokusu o načtení dat. Ať už ono načtení uspěje či neuspěje, tak se otevřený soubor automaticky uzavře. Čili to funguje tak, jako ukázka s try/finally
výše, ale kód je mnohem přehlednější a kratší.
Další čtení
Níže přidávám pár odkazů pro zájemce o další informace.
Zachytávání výjimek
Ahoj Petře,
ještě bych se zmínil o variantě příkazu
with
, která povoluje mít za klíčovým slovemwith
více kontextových výrazů, vzájemně od sebe oddělených čárkou. Této konstrukce lze využít k zachytávání výjimek vyvolaných uvnitř těla příkazuwith
, což může být užitečné, chceme-li například informovat uživatele o (ne)úspěchu dané operace. Příklad:Zde, pokud operace
open
neboread
selžou, tak vyvolají výjimku, a informace o této výjimce jsou následně uloženy doeh
, z níž si je lze získat (samozřejmě vše, co bylo owith
popsáno v článku, platí i v tomto případě).Jirka
PS: Pokud by jsi měl nějaké elegantnější řešení, jak se s daným problémem vypořádat, tak ho klidně uveď ;)