Wciąż uczę się Pythona i mam wątpliwości:
W pythonie 2.6.x zwykle deklaruję kodowanie w nagłówku pliku w ten sposób (jak w PEP 0263 )
# -*- coding: utf-8 -*-
Następnie moje napisy są zapisywane jak zwykle:
a = "A normal string without declared Unicode"
Ale za każdym razem, gdy widzę kod projektu w Pythonie, kodowanie nie jest zadeklarowane w nagłówku. Zamiast tego jest deklarowany w każdym łańcuchu w następujący sposób:
a = u"A string with declared Unicode"
Co za różnica? Jaki jest tego cel? Wiem, że Python 2.6.x domyślnie ustawia kodowanie ASCII, ale można je zastąpić deklaracją nagłówka, więc jaki jest cel deklaracji ciągu?
Dodatek: Wygląda na to, że pomyliłem kodowanie plików z kodowaniem ciągów. Dzięki za wyjaśnienie :)
# coding: utf8
jest wystarczająco dobry, nie ma potrzeby-*-
# coding: utf-8
.#coding=utf-8
. python.org/dev/peps/pep-0263Odpowiedzi:
To dwie różne rzeczy, o czym wspominali inni.
Kiedy określasz
# -*- coding: utf-8 -*-
, mówisz Pythonowi, że zapisany plik źródłowy toutf-8
. Wartość domyślna dla Pythona 2 to ASCII (dla Pythona 3 jest toutf-8
). Ma to tylko wpływ na to, jak interpreter odczytuje znaki w pliku.Ogólnie rzecz biorąc, prawdopodobnie nie jest najlepszym pomysłem osadzanie w pliku dużych znaków Unicode, niezależnie od tego, jakie jest kodowanie; możesz użyć znaków ucieczki Unicode, które działają w obu kodowaniach.
Kiedy deklarujesz ciąg z
u
przednią , na przykładu'This is a string'
, mówi kompilatorowi Pythona, że ciąg jest Unicode, a nie bajty. Jest to obsługiwane głównie w sposób przejrzysty przez tłumacza; Najbardziej oczywistą różnicą jest to, że można teraz osadzać znaki Unicode w łańcuchu (to znaczy, żeu'\u2665'
jest teraz legalny). Możesz użyć,from __future__ import unicode_literals
aby ustawić go jako domyślny.Dotyczy to tylko Pythona 2; w Pythonie 3 wartością domyślną jest Unicode i musisz podać
b
przednią literę (np.b'These are bytes'
w celu zadeklarowania sekwencji bajtów).źródło
Jak powiedzieli inni,
# coding:
określa kodowanie, w jakim zapisywany jest plik źródłowy. Oto kilka przykładów ilustrujących to:Plik zapisany na dysku jako cp437 (moje kodowanie konsoli), ale nie zadeklarowano kodowania
Wynik:
Wyjście pliku z
# coding: cp437
dodanymi:Początkowo Python nie znał kodowania i narzekał na znak spoza ASCII. Gdy już poznał kodowanie, ciąg bajtów pobierał bajty, które faktycznie znajdowały się na dysku. W przypadku ciągu znaków Unicode, Python odczytał \ x81, wiedział, że w cp437 był to ü i zdekodował go do punktu kodowego Unicode dla ü, czyli U + 00FC. Gdy łańcuch bajtów został wydrukowany, Python wysłał wartość szesnastkową
81
bezpośrednio do konsoli. Po wydrukowaniu łańcucha Unicode Python poprawnie wykrył kodowanie mojej konsoli jako cp437 i przetłumaczył Unicode ü na wartość cp437 dla ü .Oto, co dzieje się z plikiem zadeklarowanym i zapisanym w UTF-8:
W UTF-8 ü jest kodowane jako bajty szesnastkowe
C3 BC
, więc ciąg bajtów zawiera te bajty, ale łańcuch Unicode jest identyczny z pierwszym przykładem. Python odczytał dwa bajty i poprawnie je zdekodował. Python niepoprawnie wydrukował łańcuch bajtów, ponieważ wysłał dwa bajty UTF-8 reprezentujące ü bezpośrednio do mojej konsoli cp437.Tutaj plik jest zadeklarowany jako cp437, ale zapisany w UTF-8:
Ciąg bajtów nadal zawiera bajty na dysku (bajty szesnastkowe UTF-8
C3 BC
), ale zinterpretował je jako dwa znaki cp437 zamiast jednego znaku zakodowanego w UTF-8. Te dwa znaki zostały przetłumaczone na punkty kodowe Unicode i wszystko jest drukowane nieprawidłowo.źródło
To nie ustawia formatu ciągu; ustawia format pliku. Nawet z tym nagłówkiem
"hello"
jest ciągiem bajtów, a nie ciągiem Unicode. Aby uzyskać Unicode, będziesz musiał używać gou"hello"
wszędzie. Nagłówek to tylko wskazówka, jakiego formatu użyć podczas czytania.py
pliku.źródło
Definicja nagłówka służy do definiowania kodowania samego kodu, a nie wynikowych ciągów w czasie wykonywania.
umieszczenie znaku innego niż ASCII, takiego jak ۲ w skrypcie Pythona bez definicji nagłówka utf-8 spowoduje wyświetlenie ostrzeżenia
źródło
Zrobiłem następujący moduł o nazwie unicoder, aby móc wykonać transformację na zmiennych:
Następnie w swoim programie możesz wykonać następujące czynności:
źródło