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: