Evitarea problemelor de backslash din Windows cu șirurile de caractere brute din Python

Sunt un tip Unix, dar participanții la cursurile mele de Python folosesc în marea lor majoritate Windows. Inevitabil, atunci când ajungem să vorbim despre lucrul cu fișiere în Python, cineva va dori să deschidă un fișier folosind calea completă a fișierului. Și vor sfârși prin a scrie ceva de genul acesta:

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

Dar când studenții mei încearcă să deschidă fișierul, descoperă că Python le dă o eroare, indicând că fișierul nu există! Cu alte cuvinte, ei scriu:

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

Care este problema? Acest lucru pare a fi un Python destul de standard, nu?

Amintiți-vă că șirurile de caractere în Python conțin în mod normal caractere. Aceste caractere sunt în mod normal imprimabile, dar există momente în care doriți să includeți un caracter care nu este cu adevărat imprimabil, cum ar fi o linie nouă. În aceste cazuri, Python (la fel ca multe limbaje de programare) include coduri speciale care vor insera caracterul special.

Cel mai cunoscut exemplu este newline, alias ‘\n’, sau ASCII 10. Dacă doriți să inserați o linie nouă în șirul dumneavoastră Python, atunci puteți face acest lucru cu ‘\n’ în mijloc. De exemplu:

s = 'abc\ndef\nghi'

Când vom imprima șirul, vom vedea:

>>> print(s)abcdefghi

Ce se întâmplă dacă doriți să imprimați un ‘\n’ literal în codul dumneavoastră? Adică, doriți o backslash, urmată de un „n”? Atunci va trebui să dublați backslash-ul: „\\” într-un șir de caractere va avea ca rezultat un singur caracter backslash. Următorul „n” va fi apoi normal. De exemplu:

s = 'abc\ndef\nghi'

Când spunem:

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

Este destul de bine cunoscut faptul că trebuie să vă păziți de această traducere atunci când lucrați cu \n. Dar ce alte caractere necesită acest lucru? Se pare că mai multe decât s-ar aștepta mulți oameni:

  • \a – alarmă (ASCII 7)
  • \b – backspace (ASCII
  • \f – form feed
  • \n – newline
  • \r – carriage return
  • \t – tabulator
  • \v – tabulație verticală
  • \ooo – caracter cu valoare octală ooo
  • \xhh – caracter cu valoare hexagonală hh
  • \N{name} – caracter Unicode {name}
  • \uxxxx – caracter Unicode cu valoare 16-bit hexazeci de 16 biți xxxx
  • \Uxxxxxxxx – Caracter Unicode cu valoare hexazeci de 32 de biți xxxxxxxx

Din experiența mea, este extrem de puțin probabil să folosiți unele dintre acestea în mod intenționat. Adică, când a fost ultima dată când ați avut nevoie să folosiți un caracter de avans de formă? Sau o tabulație verticală? Știu – a fost aproximativ în aceeași zi în care v-ați condus dinozaurul la serviciu, după ce ați săpat un puț în curtea din spate pentru apă potabilă.

Dar aproape de fiecare dată când predau Python – adică în fiecare zi – cineva din clasa mea se lovește din greșeală de unul dintre aceste caractere. Acest lucru se datorează faptului că combinația dintre backslash-urile folosite de aceste caractere și backslash-urile folosite în căile de acces din Windows creează erori inevitabile și frustrante.

Îți amintești acea cale de acces pe care am menționat-o în partea de sus a postării de pe blog, care pare atât de inocentă?

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

Ca aceasta conține un caracter „\a”. Ceea ce înseamnă că atunci când îl imprimăm:

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

Vezi? „\a” a dispărut, fiind înlocuit cu un caracter de alarmă. Dacă ești norocos.

Deci, ce putem face în legătură cu asta? Dublați backslash-urile, bineînțeles. Trebuie să le dublați doar pe cele care vor fi transformate în caractere speciale, din tabelul pe care l-am reprodus mai sus: Dar, haideți, chiar vă veți aminti că „\f” este special, dar „\g” nu este? Probabil că nu.

De aceea, regula mea generală, și ceea ce le spun studenților mei, este că ar trebui să dubleze întotdeauna backslash-urile în căile de acces din Windows. Cu alte cuvinte:

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

Funcționează!

Dar așteptați: Nimeni nu vrea să se plimbe cu adevărat prin numele căilor de acces, dublând fiecare backslash, nu-i așa? Bineînțeles că nu.

Acesta este punctul în care șirurile brute ale lui Python pot fi de ajutor. Mă gândesc la șirurile brute în două moduri diferite:

  • șiruri de tip „ceea ce vezi este ceea ce primești”
  • șiruri de backslash-uri dublate automat în șiruri

În ambele cazuri, efectul este același: toate backslash-urile sunt dublate, astfel încât toate aceste caractere speciale enervante și ciudate dispar. Ceea ce este grozav atunci când lucrați cu căile de acces din Windows.

Tot ce trebuie să faceți este să puneți un „r” înaintea ghilimelelor de deschidere (simple sau duble):

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

Rețineți că un „șir brut” nu este de fapt un tip diferit de șir. Este doar un alt mod de a introduce un șir în Python. Dacă verificați, type(filename) va fi tot „str”, dar toate backslash-urile sale vor fi dublate.

Linia de jos: Dacă folosiți Windows, atunci ar trebui să scrieți toate șirurile de nume de drumuri codificate în mod greșit ca șiruri brute. Chiar dacă sunteți un expert Python, vă pot spune din experiență că vă veți lovi de această problemă uneori. Și chiar și pentru cei mai buni dintre noi, găsirea acelui „\f” rătăcit într-un șir de caractere poate fi consumatoare de timp și frustrantă.

PS: Da, este adevărat că utilizatorii de Windows pot să ocolească această problemă prin utilizarea barelor frânte, așa cum facem noi, cei de la Unix. Dar studenților mei li se pare că acest lucru are un aspect deosebit de ciudat, așa că nu îl văd ca pe o soluție de uz general.

Ai apreciat acest articol? Alăturați-vă celor peste 11.000 de alți dezvoltatori care primesc gratuit și săptămânal buletinul meu informativ „Better developers”. În fiecare luni, veți primi un articol ca acesta despre dezvoltarea de software și Python:

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.