Historia pytania:
Kodowanie (encoding) i dekodowanie (decoding) danych stały się aktualne wraz z pojawieniem się potrzeby wymiany informacji między urządzeniami, programami i platformami, które mogą różnie interpretować znaki i ich reprezentację w pamięci. W Pythonie problem stał się istotny z powodu ścisłego podziału między ciągami znaków (str) a bajtami (bytes), zaczynając od Python 3.x, gdzie ciągi znaków to sekwencje znaków Unicode, a bajty to sekwencje bajtów.
Problem:
Pracując z plikami, sieciami i zewnętrznymi systemami, często trzeba przekształcać dane między reprezentacjami bajtowymi a ciągami znaków. Nieprawidłowe użycie kodowania może prowadzić do błędów UnicodeEncodeError i UnicodeDecodeError, naruszenia integralności danych i problemów z obsługą różnych języków.
Rozwiązanie:
W Pythonie do konwersji ciągu znaków na bajty używa się metody .encode(), a do odwrotnej konwersji — .decode(). Najbardziej powszechnym kodowaniem jest "utf-8":
text = "Cześć, świecie!" encoded = text.encode('utf-8') # Kodujemy ciąg znaków na bajty print(encoded) # b'\xd0\x9f\xd1\x80...' decoded = encoded.decode('utf-8') # Dekodujemy z powrotem na ciąg znaków print(decoded) # 'Cześć, świecie!'
Kluczowe cechy:
open(..., encoding='utf-8')).Co się stanie, jeśli spróbujesz dekodować bajtowy ciąg ze złym kodowaniem?
Przy próbie dekodowania bajtów przy użyciu nieprawidłowego kodowania pojawi się błąd lub otrzymasz niepoprawny ciąg znaków. Na przykład:
b = b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82' wrong = b.decode('latin-1') print(wrong) # Wyświetli bełkot, a nie "Cześć"
Czy można łączyć ciąg znaków i bajtowy ciąg bezpośrednio za pomocą +?
Nie. Spowoduje to wyjątek TypeError.
s = "abc" b = b"def" # s + b # TypeError: can only concatenate str (not "bytes") to str
Czy można zapisywać plik tekstowy bez wyraźnie określonego kodowania?
Tak, ale jest to uważane za złą praktykę, ponieważ używa domyślnego kodowania systemowego, które zależy od ustawień systemu operacyjnego, co prowadzi do niezgodności między platformami.
Programista zapisuje plik dziennika w Windows bez podawania kodowania. Dziennik otwiera się w Linux lub Mac, ale wyświetla bełkot zamiast cyrylicy.
Zalety:
Wady:
Programista zawsze podaje encoding='utf-8' przy pracy z plikami:
with open('log.txt', 'w', encoding='utf-8') as f: f.write('Program zakończył się sukcesem')
Zalety:
Wady: