A Windows backslash problémák elkerülése a Python nyers karakterláncokkal

A Unix fickó vagyok, de a Python óráim résztvevői túlnyomórészt Windows-t használnak. Elkerülhetetlen, hogy amikor a fájlokkal való munkáról beszélgetünk Pythonban, valaki meg akar majd nyitni egy fájlt a fájl teljes elérési útvonalát használva. És végül valami ilyesmit fognak írni:

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

De amikor a diákjaim megpróbálják megnyitni a fájlt, rájönnek, hogy a Python hibát ad, jelezve, hogy a fájl nem létezik! Más szóval azt írják:

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

Mi a probléma? Ez eléggé szabványos Pythonnak tűnik, nem?

Emlékezzünk arra, hogy a Pythonban a karakterláncok általában karaktereket tartalmaznak. Ezek a karakterek általában nyomtathatóak, de vannak esetek, amikor olyan karaktert akarsz beilleszteni, ami nem igazán nyomtatható, például egy újsor. Ezekre az esetekre a Python (mint sok más programozási nyelv) speciális kódokat tartalmaz, amelyek beillesztik a speciális karaktert.

A legismertebb példa a newline, más néven ‘\n’, vagy ASCII 10. Ha egy newline-t akarsz beszúrni a Python karakterláncodba, akkor ezt a ‘\n’ karakterrel teheted meg. Például:

s = 'abc\ndef\nghi'

Ha kiírjuk a karakterláncot, azt látjuk:

>>> print(s)abcdefghi

Mi van akkor, ha egy szó szerinti ‘\n’-t szeretnénk kiírni a kódunkban? Vagyis egy backslash-t akarsz, amit egy “n” követ? Akkor meg kell dupláznia a backslash-t:A “\\” egy karakterláncban egyetlen backslash karaktert eredményez. Az ezt követő “n” ezután normális lesz. Például:

s = 'abc\ndef\nghi'

Mikor azt mondjuk:

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

Ez eléggé közismert, hogy az \n-rel dolgozva óvakodni kell ettől a fordítástól. De milyen más karakterek igénylik ezt? Kiderül, több, mint sokan gondolnák:

  • \a – vészcsengő (ASCII 7)
  • \b – backspace (ASCII
  • \f – form feed
  • \n – újsor
  • \r – carriage return
  • \t – tabulátor
  • \v – függőleges tabulátor
  • \ooo – karakter oktális értékkel ooo
  • \xhh – karakter hexa értékkel hh
  • \N{név} – Unicode karakter {név}
  • \uxxxx – Unicode karakter 16-mal.xxxx
  • \Uxxxxxxxxxxxx – Unicode karakter 32 bites hexa értékkel xxxxxxxx

A tapasztalatom szerint, rendkívül valószínűtlen, hogy ezek közül néhányat szándékosan használsz. Úgy értem, mikor volt utoljára szükséged form feed karakter használatára? Vagy egy függőleges tabulátor? Tudom – nagyjából aznap, amikor a dinoszauruszodat vezetted munkába, miután kutat ástál az udvarodban ivóvízért.

De majdnem minden alkalommal, amikor Pythont tanítok – vagyis minden nap – valaki az osztályomban véletlenül belebotlik valamelyik ilyen karakterbe. Ez azért van, mert az ezen karakterek által használt backslashek és a Windows útvonalakban használt backslashek kombinációja elkerülhetetlen és frusztráló hibákat okoz.

Emlékszel arra az útvonalra, amit a blogbejegyzés elején említettem, és ami olyan ártatlannak tűnik?

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

Ez egy “\a” karaktert tartalmaz. Ami azt jelenti, hogy amikor kinyomtatjuk:

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

See? Az “\a” eltűnik, helyébe egy vészcsengő karakter lép. Ha szerencsénk van.

Szóval, mit tehetünk ez ellen? Természetesen megduplázzuk a backslasheket. Csak azokat kell megduplázni, amelyek speciális karakterekké válnának, a táblázatból, amit fentebb reprodukáltam: De ugyan már, tényleg emlékszel arra, hogy az “\f” különleges, de az “\g” nem az? Valószínűleg nem.

Az általános szabályom tehát az, és ezt mondom a diákjaimnak is, hogy mindig duplázzák meg a backslash-eket a Windows elérési útvonalakban. Más szóval:

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

Ez működik!

De várjunk csak: Ugye senki sem akar tényleg végigbogarászni az elérési útvonalakon, megduplázva minden backslash-t? Természetesen nem.

Ez az a pont, ahol a Python nyers karakterláncai segíthetnek. Én kétféleképpen gondolok a nyers karakterláncokra:

  • amit látsz, azt kapod
  • automatikusan megduplázott backslashek a karakterláncokban

A hatás mindkét esetben ugyanaz: minden backslash megduplázódik, így ezek a bosszantó és furcsa speciális karakterek eltűnnek. Ami nagyszerű, ha Windows elérési utakkal dolgozol.

Mindössze egy “r”-t kell tenned a nyitó idézőjelek (szimpla vagy dupla) elé:

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

Megjegyezzük, hogy a “nyers karakterlánc” valójában egyáltalán nem más típusú karakterlánc. Ez csak egy másik módja annak, hogy egy karakterláncot bevigyünk a Pythonba. Ha ellenőrzöd, a type(fájlnév) még mindig “str” lesz, de a backslash-jei mind megduplázódnak.

Az alsó sorban: Ha Windows-t használsz, akkor az összes keményen kódolt pathname stringet csak nyers stringként írd be. Még ha Python-szakértő is vagy, tapasztalatból mondhatom, hogy néha bele fogsz ütközni ebbe a problémába. És még a legjobbak számára is időigényes és frusztráló lehet megtalálni azt a kóbor “\f”-et egy karakterláncban.

PS: Igen, igaz, hogy a Windows-felhasználók megkerülhetik ezt a problémát azáltal, hogy a Unix-felhasználókhoz hasonlóan átlós írásjeleket használnak. De a diákjaim ezt különösen furcsának találják, és ezért nem látom általános érvényű megoldásnak.

A cikk tetszett? Csatlakozzon több mint 11 000 másik fejlesztőhöz, akik megkapják az ingyenes, heti rendszerességgel megjelenő “Jobb fejlesztők” hírlevelemet. Minden hétfőn kapsz egy ehhez hasonló cikket a szoftverfejlesztésről és a Pythonról:

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.