Č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 slovemwithví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
openneboreadselž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 owithpopsá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ď ;)