Vyhnutí se problémům se zpětnými lomítky systému Windows v nezpracovaných řetězcích Pythonu

Jsem unixový uživatel, ale účastníci mých kurzů Pythonu v drtivé většině používají Windows. Když se dostaneme k povídání o práci se soubory v Pythonu, někdo bude nevyhnutelně chtít otevřít soubor pomocí kompletní cesty k souboru. A nakonec napíše něco takového:

filename = 'c:\abc\def\ghi.txt'

Ale když se moji studenti pokusí soubor otevřít, zjistí, že jim Python hlásí chybu s tím, že soubor neexistuje! Jinými slovy, napíší:

for one_line in open(filename): print(one_line)

V čem je problém? To vypadá jako docela standardní Python, ne?“

Pamatujte, že řetězce v Pythonu normálně obsahují znaky. Tyto znaky jsou normálně tisknutelné, ale jsou případy, kdy chcete zahrnout znak, který ve skutečnosti tisknutelný není, například nový řádek. V takových případech Python (stejně jako mnoho jiných programovacích jazyků) obsahuje speciální kódy, které tento speciální znak vloží.

Nejznámějším příkladem je nový řádek, známý také jako ‚\n‘, neboli ASCII 10. V takovém případě je třeba použít speciální kód. Pokud chcete do řetězce v jazyce Python vložit nový řádek, můžete tak učinit pomocí ‚\n‘ uprostřed. Například:

s = 'abc\ndef\nghi'

Pokud řetězec vypíšeme, uvidíme:

>>> print(s)abcdefghi

Co když chcete ve svém kódu vypsat doslovné ‚\n‘? To znamená, že chcete zpětné lomítko následované písmenem „n“? Pak budete muset zpětné lomítko zdvojit:Výsledkem „\\“ v řetězci bude jeden znak zpětného lomítka. Následující „n“ pak bude normální. Například:

s = 'abc\ndef\nghi'

Když řekneme:

>>> print(s)abc\ndef\nghi

Je celkem dobře známo, že při práci s \n je třeba tento překlad hlídat. Ale které jiné znaky to vyžadují? Ukazuje se, že více, než by mnozí čekali:

  • \a – budík (ASCII 7)
  • \b – backspace (ASCII
  • \f – form feed
  • \n – nový řádek
  • \r – návrat vozíku
  • \t – tabulátor
  • \v – vertikální tabulátor
  • \ooo – znak s osmičkovou hodnotou ooo
  • \xhh – znak s šestnáctkovou hodnotou hh
  • \N{jméno} – znak Unicode {jméno}
  • \uxxxx – znak Unicode s 16-ti znakybitovou hexadecimální hodnotou xxxx
  • \Uxxxxxxxx – znak Unicode s 32bitovou hexadecimální hodnotou xxxxxxxx

Podle mých zkušeností, je velmi nepravděpodobné, že byste některé z nich použili záměrně. Vždyť kdy jste naposledy potřebovali použít znak form feed? Nebo vertikální tabulátor? Já vím – bylo to zhruba ve stejný den, kdy jste odvezli svého dinosaura do práce poté, co jste si na dvorku vykopali studnu na pitnou vodu.

Ale téměř pokaždé, když učím Python – což je každý den – někdo v mé třídě na některý z těchto znaků omylem narazí. Je to proto, že kombinace zpětných lomítek používaných těmito znaky a zpětných lomítek používaných v cestách systému Windows vytváří nevyhnutelné a frustrující chyby.

Pamatujete si na tu cestu, kterou jsem zmínil na začátku příspěvku, která vypadá tak nevinně?

filename = 'c:\abc\def\ghi.txt'

Obsahuje znak „\a“. Což znamená, že když ji vypíšeme:

>>> print(filename)c:bc\def\ghi.txt

Vidíte? „\a“ zmizí a nahradí ho znak budíku. Při troše štěstí.

Takže, co s tím můžeme dělat? Samozřejmě zdvojnásobit zpětná lomítka. Stačí zdvojnásobit ta, která by se změnila na speciální znaky, z tabulky, kterou jsem reprodukoval výše: Ale no tak, opravdu si pamatujete, že „\f“ je speciální, ale „\g“ ne? Pravděpodobně ne.

Takže moje obecné pravidlo, které říkám i svým studentům, je, že by měli vždy zdvojovat zpětná lomítka v cestách Windows. Jinými slovy:

>>> filename = 'c:\abc\def\ghi.txt'>>> print(filename)c:\abc\def\ghi.txt

Funguje to!“

Ale počkejte: Nikomu se přece nechce procházet své cesty a zdvojovat každé zpětné lomítko, že? Jistěže ne.

Tady mohou pomoci surové řetězce jazyka Python. O raw řetězcích přemýšlím dvěma různými způsoby:

  • co vidíš, to dostaneš
  • automaticky zdvojená zpětná lomítka v řetězcích

V obou případech je efekt stejný: všechna zpětná lomítka jsou zdvojená, takže všechny ty otravné a divné speciální znaky zmizí. Což je skvělé, když pracujete s cestami v systému Windows.

Jediné, co musíte udělat, je dát před otevírací uvozovky (jednoduché nebo dvojité) písmeno „r“:

>>> filename = r'c:\abc\def\ghi.txt'>>> print(filename)c:\abc\def\ghi.txt

Všimněte si, že „surový řetězec“ ve skutečnosti vůbec není jiný typ řetězce. Je to jen jiný způsob zadávání řetězce do jazyka Python. Pokud si to ověříte, type(název souboru) bude stále „str“, ale všechna jeho zpětná lomítka budou zdvojená.

Dolní řádek: Pokud používáte systém Windows, měli byste všechny řetězce s pevně zadanými názvy cest zapisovat jako surové řetězce. I když jste odborník na Python, mohu vám ze zkušenosti říci, že na tento problém občas narazíte. A i pro ty nejlepší z nás může být hledání zbloudilého „\f“ v řetězci časově náročné a frustrující.

PS: Ano, je pravda, že uživatelé Windows to mohou obejít použitím předních lomítek, jako to děláme my, unixoví uživatelé. Ale mým studentům to připadá obzvlášť divně vypadající, a tak to nepovažuji za univerzální řešení.

Líbil se vám tento článek? Připojte se k více než 11 000 dalším vývojářům, kteří dostávají můj bezplatný týdenní zpravodaj „Lepší vývojáři“. Každé pondělí vám přijde článek, jako je tento, o vývoji softwaru a jazyku Python:

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.