"
#-*- coding:utf-8 -*-
print ("Gotówka wysłane")
"
Przy okazji testowałem różne edytory i okazało się, że niektóre (np SPE,
PyCharm, DreamPie-w tym nie ustawia kodowania) powyższy kod po uruchomieniu
poprawnie wyświetlają z polskimi znaczkami. To samo, gdy uruchomię
bezpośrednio z cmd.exe i przekierowuje wynik do pliku. Zawartośc tego pliku
notatnik wyświetlał mi poprawnie z polskimi znaczkami.
Niestety inne edytory (NetBeans, PyScripter, WingIDE, starsze wersje SPE),
taki po uruchomieniu wyświetlały z "dziwnymi znaczkami".
Traktowałem to jako ich wadę (że mają złą obsługe unicode). (bo przecież pod
czystym pythonem było OK!!)
W pracy na moim kompie ten sam kod chodził mi jak w domu, czyli w sposób
pożądany. Kod pisałem dla potrzeb innych.
Więc inne osoby uruchomiły ten kod z poziomu cmd.exe
(a dokładnie uruchmiały .bat w którym było wywołanie w:\<scieżka>\python
skrypt.py)
i im pojawiały krzaczki. Zalogowałem się na ich komputrze i mi progam dobrze
wyświetlał. Czyli domyślam jakiś problem profilu. Więc 1 pytanie:
PYTANIE 1.
Co powoduje, że powyższy kod uruchamiany na tym samym komputerze, ale u
różnych użytkowników działa dobrze lub źle.
PYTANIE 2.
Co powoduje, że w niektórych edytora powyższy kod działa "ładnie", a na
niektórych "nieładnie"
Ciąg dalszy tematu.
Czytałem howto unicode (ang), polska książki do pythona na wikibooks
(http://pl.wikibooks.org/wiki/Zanurkuj_w_Pythonie/) i kompletnie nie
rozumiałem spraw decode()/encode() przedrostków u"źć" unicode() itd. Dla
mnie to nieczytelne (o dokumentacji Pythona jeszcze napisze w innym poście).
Robiłem próby tak jak to rozumiałem.
Np w wiikibooks jest zapis:
"
Łańcuch znaków przechowuje znaki w zakodowanej postaci np. w systemie UTF-8,
ISO 8859-1, czy ISO 8859-4; może być wieloznaczny. Natomiast unikod jest
jednoznaczny, więc nie jest zakodowany w tego typu systemach kodowania.
Ponieważ łańcuch znaków jest zakodowany, musimy odkodować (za pomocą
decode), aby otrzymać niezakodowany unikod. Z kolei unikod, ponieważ jest
niezakodowany, musimy zakodować (za pomocą encode), aby otrzymać zakodowany
łańcuch znaków.
"
Dziś wiem jak go interpretować. Ale na początku źle zrozumiałem.
Sądziłem, że jak mam unicode to musze go zakodować (cytat: "Z kolei unikod,
ponieważ jest niezakodowany, musimy zakodować").
Oczywiście robiąc próby na odbiorcy miałem zero powodzenia. NIC nie
działało. Kompletna porażka.
Jak dziś pojawił problem z tymi znaczkami to powrocie z pracy zaglądam na
grupę i szukam posty z tematem "unicode", czytam i wyciągam wnioski. Na
początek coś co niby wiedziałem, ale nie rozumiałem.!!!
*********
Unicode i sposób kodowania plików to 2 RÓŻNE sprawy. Że unicode jest jeden,
natomiast sposobów ZAPISANIA (ang. encodowania) unicodu jest wiele. np
UTF-8, UTF16, itd.
*********
Czyli moje oznaczanie plików UTF-8 NIC NIE ZNACZY! Ze dopóki nie wskaże
Pythonowi, że chcę na wyjściu mieć kod unicode to muszę albo mieć na wejściu
unicod, lub ODCZYTAC/ODSZYFROWAĆ (decode) zapisany teks do kodu unicod.
Czyli, że można stosować konstrukcje:
a) print unicode("Gotówka wysłane",'utf-8') odszyfrowanie do unicode
stringu zaszyfrowanego UTF-8
b) print ("Gotówka wysłane").decode('utf-8') odszyfrowanie do (czego??)
stringu zaszyfrowanego UTF-8
c) print (u"Gotówka wysłane") jawne wskazanie, że
string źródłowy to unicod.
Testuję więc powyższe na programie PyScripter (czyli tam gdzie źle
wyświetlały polskie znaczki na wyjściu).
Efekt? Pojawiają się polskie znaczki.
Ale tu pojawiają schody.
Testuję ten sam kod na PyCharm i SPE 0.8.4.c (czyli tam gdzie wcześniej nie
bawiłem tymi bajerami) i pojawia błąd:
========================
print unicode("Gotówka wysłane",'utf-8') odszyfrowanie do unicode stringu
zaszyfrowanego UTF-8
^
SyntaxError: invalid syntax
Script terminated.
========================
W samym czystym pythonie a) i b) powodują błąd, jedynie c) działa poprawnie.
PYTANIE 3
Co powoduje, ten niby prawidłowy kod jednak jest nieprawidłowy pod tymi
edytorami? (czyli wraca pytanie 2 - skąd te różnice?)
PYTANIE 4
Czemu musze robić np ("Gotówka wysłane").decode('utf-8') skoro jest nagówek
#-*- coding:utf-8 -*-
Przecież ten nagłówek jawnie wskazuje, że mam 'utf-8' więc po co muszę to
wskazywać w kodzie? czemu sam python tego nie zauważa ?.
Uogólniając co robi kontrukcja #-*- coding:utf-8 -*- ?
Gdybym miał strzelać powiedziałby, że dla Pythona nie znaczy NIC, że to
informacja dla EDYTORA.
PYTANIE 5
W którymś poście na grupie pojawia zapis:
sys.setdefaultencoding('utf8')
czyli coś o czym wcześniej nie czytałem. i pytanie co robi ten kod?
PS. Może nadal nie rozumiem tego co myślałem że rozumiem. Proszę o odpowiedź
osoby, które rozumieją to i potrafią mi to sensownie wyjasnić.
PS2. Wg mnie istnieje silna potrzeba poprawienia opisu dotyczącego
unicode/decode/itd w obecnej dokumentacji, która przez skąpą ilość
przykładów jest dla nowych programistów Pythona NIEZROZUMIAŁA. I konieczne
dopisania tam tych niuansów które podniosłem powyżej.
W wikibooks sam spóbuję coś poprawić, ale dopiero jak otrzymam odpowieź
którą zrozumiem, dzięki czemu będę wiedział co dopiasać.
PS3. Czy ktoś wie, czemu w wikipedi wciąż brak edytora wizualnego (jak
allegro i innych), tylko trzeba poprawiać kodując HTML. Przecież to
ogranicza grono osób, które może coś sensownego dopisać, bo znajomośc HTML
jest RZADKA.
Pozdr
PiotrPastuszka
"
#-*- coding:utf-8 -*-
print ("Got�wka wys�ane")
"
Przy okazji testowa�em r�ne edytory i okaza�o si�, �e niekt�re (np SPE,
PyCharm, DreamPie-w tym nie ustawia kodowania) powy�szy kod po uruchomieniu
poprawnie wy�wietlaj� z polskimi znaczkami. To samo, gdy uruchomi�
bezpo�rednio z cmd.exe i przekierowuje wynik do pliku. Zawarto�c tego pliku
notatnik wy�wietla� mi poprawnie z polskimi znaczkami.
Niestety inne edytory (NetBeans, PyScripter, WingIDE, starsze wersje SPE),
taki po uruchomieniu wy�wietla�y z "dziwnymi znaczkami".
Traktowa�em to jako ich wad� (�e maj� z�� obs�uge unicode). (bo przecie� pod
czystym pythonem by�o OK!!)
W pracy na moim kompie ten sam kod chodzi� mi jak w domu, czyli w spos�b
po��dany. Kod pisa�em dla potrzeb innych.
Wi�c inne osoby uruchomi�y ten kod z poziomu cmd.exe
(a dok�adnie uruchmia�y .bat w kt�rym by�o wywo�anie w:\<scie�ka>\python
skrypt.py)
i im pojawia�y krzaczki. Zalogowa�em si� na ich komputrze i mi progam dobrze
wy�wietla�. Czyli domy�lam jaki� problem profilu. Wi�c 1 pytanie:
PYTANIE 1.
Co powoduje, �e powy�szy kod uruchamiany na tym samym komputerze, ale u
r�nych u�ytkownik�w dzia�a dobrze lub �le.
PYTANIE 2.
Co powoduje, �e w niekt�rych edytora powy�szy kod dzia�a "�adnie", a na
niekt�rych "nie�adnie"
Ci�g dalszy tematu.
Czyta�em howto unicode (ang), polska ksi��ki do pythona na wikibooks
(http://pl.wikibooks.org/wiki/Zanurkuj_w_Pythonie/) i kompletnie nie
rozumia�em spraw decode()/encode() przedrostk�w u"��" unicode() itd. Dla
mnie to nieczytelne (o dokumentacji Pythona jeszcze napisze w innym po�cie).
Robi�em pr�by tak jak to rozumia�em.
Np w wiikibooks jest zapis:
"
�a�cuch znak�w przechowuje znaki w zakodowanej postaci np. w systemie UTF-8,
ISO 8859-1, czy ISO 8859-4; mo�e by� wieloznaczny. Natomiast unikod jest
jednoznaczny, wi�c nie jest zakodowany w tego typu systemach kodowania.
Poniewa� �a�cuch znak�w jest zakodowany, musimy odkodowa� (za pomoc�
decode), aby otrzymaďż˝ niezakodowany unikod. Z kolei unikod, poniewaďż˝ jest
niezakodowany, musimy zakodowaďż˝ (za pomocďż˝ encode), aby otrzymaďż˝ zakodowany
�a�cuch znak�w.
"
Dzi� wiem jak go interpretowa�. Ale na pocz�tku �le zrozumia�em.
S�dzi�em, �e jak mam unicode to musze go zakodowa� (cytat: "Z kolei unikod,
poniewaďż˝ jest niezakodowany, musimy zakodowaďż˝").
Oczywi�cie robi�c pr�by na odbiorcy mia�em zero powodzenia. NIC nie
dzia�a�o. Kompletna pora�ka.
Jak dzi� pojawi� problem z tymi znaczkami to powrocie z pracy zagl�dam na
grup� i szukam posty z tematem "unicode", czytam i wyci�gam wnioski. Na
pocz�tek co� co niby wiedzia�em, ale nie rozumia�em.!!!
*********
Unicode i spos�b kodowania plik�w to 2 RӯNE sprawy. �e unicode jest jeden,
natomiast sposob�w ZAPISANIA (ang. encodowania) unicodu jest wiele. np
UTF-8, UTF16, itd.
*********
Czyli moje oznaczanie plik�w UTF-8 NIC NIE ZNACZY! Ze dop�ki nie wska�e
Pythonowi, �e chc� na wyj�ciu mie� kod unicode to musz� albo mie� na wej�ciu
unicod, lub ODCZYTAC/ODSZYFROWAďż˝ (decode) zapisany teks do kodu unicod.
Czyli, �e mo�na stosowa� konstrukcje:
a) print unicode("Got�wka wys�ane",'utf-8') odszyfrowanie do unicode
stringu zaszyfrowanego UTF-8
b) print ("Got�wka wys�ane").decode('utf-8') odszyfrowanie do (czego??)
stringu zaszyfrowanego UTF-8
c) print (u"Got�wka wys�ane") jawne wskazanie, �e
string �r�d�owy to unicod.
Testuj� wi�c powy�sze na programie PyScripter (czyli tam gdzie �le
wy�wietla�y polskie znaczki na wyj�ciu).
Efekt? Pojawiajďż˝ siďż˝ polskie znaczki.
Ale tu pojawiajďż˝ schody.
Testuj� ten sam kod na PyCharm i SPE 0.8.4.c (czyli tam gdzie wcze�niej nie
bawi�em tymi bajerami) i pojawia b��d:
========================
print unicode("Got�wka wys�ane",'utf-8') odszyfrowanie do unicode stringu
zaszyfrowanego UTF-8
^
SyntaxError: invalid syntax
Script terminated.
========================
W samym czystym pythonie a) i b) powoduj� b��d, jedynie c) dzia�a poprawnie.
PYTANIE 3
Co powoduje, ten niby prawid�owy kod jednak jest nieprawid�owy pod tymi
edytorami? (czyli wraca pytanie 2 - sk�d te r�nice?)
PYTANIE 4
Czemu musze robi� np ("Got�wka wys�ane").decode('utf-8') skoro jest nag�wek
#-*- coding:utf-8 -*-
Przecie� ten nag��wek jawnie wskazuje, �e mam 'utf-8' wi�c po co musz� to
wskazywa� w kodzie? czemu sam python tego nie zauwa�a ?.
Uog�lniaj�c co robi kontrukcja #-*- coding:utf-8 -*- ?
Gdybym mia� strzela� powiedzia�by, �e dla Pythona nie znaczy NIC, �e to
informacja dla EDYTORA.
PYTANIE 5
W kt�rym� po�cie na grupie pojawia zapis:
sys.setdefaultencoding('utf8')
czyli co� o czym wcze�niej nie czyta�em. i pytanie co robi ten kod?
PS. Mo�e nadal nie rozumiem tego co my�la�em �e rozumiem. Prosz� o odpowied�
osoby, kt�re rozumiej� to i potrafi� mi to sensownie wyjasni�.
PS2. Wg mnie istnieje silna potrzeba poprawienia opisu dotycz�cego
unicode/decode/itd w obecnej dokumentacji, kt�ra przez sk�p� ilo��
przyk�ad�w jest dla nowych programist�w Pythona NIEZROZUMIA�A. I konieczne
dopisania tam tych niuans�w kt�re podnios�em powy�ej.
W wikibooks sam sp�buj� co� poprawi�, ale dopiero jak otrzymam odpowie�
kt�r� zrozumiem, dzi�ki czemu b�d� wiedzia� co dopiasa�.
PS3. Czy kto� wie, czemu w wikipedi wci�� brak edytora wizualnego (jak
allegro i innych), tylko trzeba poprawia� koduj�c HTML. Przecie� to
ogranicza grono os�b, kt�re mo�e co� sensownego dopisa�, bo znajomo�c HTML
jest RZADKA.
Pozdr
PiotrPastuszka
"
#-*- coding:utf-8 -*-
print ("Gotówka wysłane")
"
Przy okazji testowałem różne edytory i okazało się, że niektóre (np SPE,
PyCharm, DreamPie-w tym nie ustawia kodowania) powyższy kod po uruchomieniu
poprawnie wyświetlają z polskimi znaczkami. To samo, gdy uruchomię
bezpośrednio z cmd.exe i przekierowuje wynik do pliku. Zawartośc tego pliku
notatnik wyświetlał mi poprawnie z polskimi znaczkami.
Niestety inne edytory (NetBeans, PyScripter, WingIDE, starsze wersje SPE),
taki po uruchomieniu wyświetlały z "dziwnymi znaczkami".
Traktowałem to jako ich wadę (że mają złą obsługe unicode). (bo przecież pod
czystym pythonem było OK!!)
W pracy na moim kompie ten sam kod chodził mi jak w domu, czyli w sposób
pożšdany. Kod pisałem dla potrzeb innych.
Więc inne osoby uruchomiły ten kod z poziomu cmd.exe
(a dokładnie uruchmiały .bat w którym było wywołanie w:\<scieżka>\python
skrypt.py)
i im pojawiały krzaczki. Zalogowałem się na ich komputrze i mi progam dobrze
wyświetlał. Czyli domyślam jakiś problem profilu. Więc 1 pytanie:
PYTANIE 1.
Co powoduje, że powyższy kod uruchamiany na tym samym komputerze, ale u
różnych użytkowników działa dobrze lub źle.
PYTANIE 2.
Co powoduje, że w niektórych edytora powyższy kod działa "ładnie", a na
niektórych "nieładnie"
Ciąg dalszy tematu.
Czytałem howto unicode (ang), polska książki do pythona na wikibooks
(http://pl.wikibooks.org/wiki/Zanurkuj_w_Pythonie/) i kompletnie nie
rozumiałem spraw decode()/encode() przedrostków u" ć" unicode() itd. Dla
mnie to nieczytelne (o dokumentacji Pythona jeszcze napisze w innym po cie).
Robiłem próby tak jak to rozumiałem.
Np w wiikibooks jest zapis:
"
Łańcuch znaków przechowuje znaki w zakodowanej postaci np. w systemie UTF-8,
ISO 8859-1, czy ISO 8859-4; może być wieloznaczny. Natomiast unikod jest
jednoznaczny, więc nie jest zakodowany w tego typu systemach kodowania.
Ponieważ łańcuch znaków jest zakodowany, musimy odkodować (za pomocš
decode), aby otrzymać niezakodowany unikod. Z kolei unikod, ponieważ jest
niezakodowany, musimy zakodować (za pomocą encode), aby otrzymać zakodowany
łańcuch znaków.
"
Dziś wiem jak go interpretować. Ale na początku źle zrozumiałem.
Sądziłem, że jak mam unicode to musze go zakodować (cytat: "Z kolei unikod,
ponieważ jest niezakodowany, musimy zakodować").
Oczywiście robiąc próby na odbiorcy miałem zero powodzenia. NIC nie
działało. Kompletna porażka.
Jak dziś pojawił problem z tymi znaczkami to powrocie z pracy zaglšdam na
grupę i szukam posty z tematem "unicode", czytam i wyciągam wnioski. Na
początek coś co niby wiedziałem, ale nie rozumiałem.!!!
*********
Unicode i sposób kodowania plików to 2 RÓŻNE sprawy. Że unicode jest jeden,
natomiast sposobów ZAPISANIA (ang. encodowania) unicodu jest wiele. np
UTF-8, UTF16, itd.
*********
Czyli moje oznaczanie plików UTF-8 NIC NIE ZNACZY! Ze dopóki nie wskaże
Pythonowi, że chcę na wyjściu mieć kod unicode to muszę albo mieć na wejściu
unicod, lub ODCZYTAC/ODSZYFROWAĆ (decode) zapisany teks do kodu unicod.
Czyli, że można stosować konstrukcje:
a) print unicode("Gotówka wysłane",'utf-8') odszyfrowanie do unicode
stringu zaszyfrowanego UTF-8
b) print ("Gotówka wysłane").decode('utf-8') odszyfrowanie do (czego??)
stringu zaszyfrowanego UTF-8
c) print (u"Gotówka wysłane") jawne wskazanie, że
string źródłowy to unicod.
Testuję więc powyższe na programie PyScripter (czyli tam gdzie źle
wyświetlały polskie znaczki na wyjściu).
Efekt? Pojawiają się polskie znaczki.
Ale tu pojawiają schody.
Testuję ten sam kod na PyCharm i SPE 0.8.4.c (czyli tam gdzie wcześniej nie
bawiłem tymi bajerami) i pojawia błąd:
========================
print unicode("Gotówka wysłane",'utf-8') odszyfrowanie do unicode stringu
zaszyfrowanego UTF-8
^
SyntaxError: invalid syntax
Script terminated.
========================
W samym czystym pythonie a) i b) powodują błąd, jedynie c) działa poprawnie.
PYTANIE 3
Co powoduje, ten niby prawidłowy kod jednak jest nieprawidłowy pod tymi
edytorami? (czyli wraca pytanie 2 - skąd te różnice?)
PYTANIE 4
Czemu musze robić np ("Gotówka wysłane").decode('utf-8') skoro jest nagówek
#-*- coding:utf-8 -*-
Przecież ten nagłówek jawnie wskazuje, że mam 'utf-8' więc po co muszę to
wskazywać w kodzie? czemu sam python tego nie zauważa ?.
Uogólniajšc co robi kontrukcja #-*- coding:utf-8 -*- ?
Gdybym miał strzelać powiedziałby, że dla Pythona nie znaczy NIC, że to
informacja dla EDYTORA.
PYTANIE 5
W którymś poście na grupie pojawia zapis:
sys.setdefaultencoding('utf8')
czyli coś o czym wcześniej nie czytałem. i pytanie co robi ten kod?
PS. Może nadal nie rozumiem tego co myślałem że rozumiem. Proszę o odpowiedź
osoby, które rozumieją to i potrafią mi to sensownie wyjasnić.
PS2. Wg mnie istnieje silna potrzeba poprawienia opisu dotyczącego
unicode/decode/itd w obecnej dokumentacji, która przez skąpą ilość
przykładów jest dla nowych programistów Pythona NIEZROZUMIAŁA. I konieczne
dopisania tam tych niuansów które podniosłem powyżej.
W wikibooks sam spóbuję coś poprawić, ale dopiero jak otrzymam odpowiedź
którą zrozumiem, dzięki czemu będę wiedział co dopiasać.
PS3. Czy ktoś wie, czemu w wikipedi wciąż brak edytora wizualnego (jak
allegro i innych), tylko trzeba poprawiać kodując HTML. Przecież to
ogranicza grono osób, które może coś sensownego dopisać, bo znajomość HTML
jest RZADKA.
Pozdr
PiotrPastuszka
>"
>#-*- coding:utf-8 -*-
>print ("Gotówka wysłane")
>"
Reszty teraz nie przeczytam, ale tak na szybko to tu masz buraka w tym
kodzie. Powinno być tak:
#-*- coding:utf-8 -*-
print u"Gotówka wysłane"
Czyli tekst będzie interpretowany jako unikodowy (literka u przed
cudzysłwem)
Tylko że na wyjście będzie wysyłany unicod a wyświetlanie unicodu w
konsoli to na unixie, a w windzie niet. Dlatego może wywalić enkoding
error. Dlatego na windzie robisz tak:
#-*- coding:utf-8 -*-
print u"Gotówka wysłane".encode('cp1250')
a wszędzie w kodzie przy tekstach użwyasz u"....", czyli:
a = u"Łączka zajączka"
Możesz też próbować przestawić kodowanie ogólnie dla całego pythona,
ale w to mi się nie chce nigdy bawić, bo to jakaś zamotana sprawa
jest.
Ustawienia kodowania znaków terminala/wiersza poleceń -- czy mówiąc
ogólniej -- środowiska, w którym jest uruchomiany Python. Podany przez
Ciebie kod wysyła na zewnątrz tekst zakodowany kodowaniem utf-8, więc
prawidłowe znaki wyświetlną się tylko, jeżeli środowisko (terminal/wiersz
poleceń/IDE, w którym osadzony jest python etc.) też ma ustawione utf-8
(no i jeżeli font, którego owe środowisko używa, zawiera znaki, których
użyłeś.
> PYTANIE 2.
> Co powoduje, że w niektórych edytora powyższy kod działa "ładnie", a na
> niektórych "nieładnie"
Patrz punkt 1.
> "
> Łańcuch znaków przechowuje znaki w zakodowanej postaci np. w systemie
> UTF-8,
> ISO 8859-1, czy ISO 8859-4; może być wieloznaczny. Natomiast unikod jest
> jednoznaczny, więc nie jest zakodowany w tego typu systemach kodowania.
> Ponieważ łańcuch znaków jest zakodowany, musimy odkodować (za pomocš
> decode), aby otrzymać niezakodowany unikod. Z kolei unikod, ponieważ jest
> niezakodowany, musimy zakodować (za pomocą encode), aby otrzymać
> zakodowany łańcuch znaków.
> "
Święta prawda. W Pytonie 2.x są dwa typu napisowe: str i unicode. Obiekt
str to sekwencja elementów, z których każdy reprezentowany jest przez
1 bajt czyli liczbę całkowitą od 0 do 255. A więc, by zinterpretować
obiekt str jako tekst zawierający np. polskie litery, musimy określić
jakiego *kodowania* (czyli jakie wartości lub ciągi wartości oznaczają
jakie znaki) użyjemy do jego odczytu; tak samo przy zapisie: musimy
określić *kodowanie*, czyli -- jakiej literze (znakowi) odpowiada jaka
wartość liczbowa. Przy czym są kodowania, jak np. iso-8859-2 czy cp-1250,
które wszystkim objętym przez siebie znakom przyporządkowują 1-bajtowe
wartości; a są też kodowania, takie jak utf-8 czy utf-16, w przypadku
których 1 znak może być zakodowany za pomocą kilku bajtów (np.
w przypadku utf-8 litera 'a' kodowana jest, tak jak w ASCII, za pomocą
wartości 97, ale już np. litera 'ń' -- za pomocą ciągu: 197, 132
[w zapisie szestanstkowym: 0xc5, 0x84]).
Obiekt unicode to sekwencja elementów, z których każdy reprezentowany
jest przez tzw. code point czyli liczbę całkowitą od 0 do wielu wielu
tysięcy (ilu dokładnie, to zależy od wersji standaru Unicode i innych
detali, którymi w tym momencie się nie zajmuję). A więc dany kod (code
point) odpowiada zawsze temu samemu znakowi -- określa to standard
Unicode, np. literze 'ń' odpowiada liczba 324 czuli 0x144 w zapisie
szesnastkowym (patrz: http://www.decodeunicode.org/de/u+0144). Dzięki
dużej liczbie możliwych kodów (code point'ów), standard Unicode obejmuje
znaki z bardzo wielu (jeżeli nawet nie wszystkich, to prawie wszystkich)
języków świata.
Kilka wniosków i spostrzeżeń:
* gdy przerabiamy obiekt unicode na obiekt str -- kodujemy go, np.:
napis_str = napis_unicode.encode('cp-1250')
* gdy przerabiamy obiekt str na obiekt unicode -- dekodujemy go, np.:
napis_unicode = napis_str.decode('cp-1250')
lub
napis_unicode = unicode(napis_str, 'cp-1250')
* unicode i utf-8 to dwie różne rzeczy! (to pierwsze to pythonowy typ
obiektów napisowych zawierających znaki określone standardem Unicode;
to drugie to sposób kodowania takich znaków, jeżeli są przechowywane
w postaci obiektu str).
> Czyli moje oznaczanie plików UTF-8 NIC NIE ZNACZY! Ze dopóki nie wskaże
> Pythonowi, że chcę na wyjściu mieć kod unicode to muszę albo mieć na
> wejściu unicod, lub ODCZYTAC/ODSZYFROWAĆ (decode) zapisany teks do
> kodu unicod.
> PYTANIE 4
> Czemu musze robić np ("Gotówka wysłane").decode('utf-8') skoro jest
> nagówek
> #-*- coding:utf-8 -*-
> Przecież ten nagłówek jawnie wskazuje, że mam 'utf-8' więc po co muszę to
> wskazywać w kodzie? czemu sam python tego nie zauważa ?.
> Uogólniajšc co robi kontrukcja #-*- coding:utf-8 -*- ?
> Gdybym miał strzelać powiedziałby, że dla Pythona nie znaczy NIC, że to
> informacja dla EDYTORA.
Oznaczenie na początku pliku typu # -*- coding: utf-8 -*- informuje Pythona
jakiego kodowania ma użyć, by odczytać Twój kod źródłowy (który wszak jest
plikiem, a więc w sensie logicznym -- tylko ciągiem bajtów). Deklaracja ta
musi być zgodna z faktycznym kodowaniem, jakiego dostarcza edytor tekstu,
za pomocą którego piszesz kod (inaczej Python albo od razu wywali błąd,
albo zinterpretuje Twój kod niezgodnie z Twoją intencją). Raz jeszcze
podkreślę: ta deklaracja na początku pliku dotyczy *wyłącznie* kodowania
*kodu źródłowego* Twojego programu, i niczego innego w tym programie.
A więc, jeżeli Twój edytor jest ustawiony na utf-8 i jeżeli napiszesz:
# -*- coding: utf-8 -*-
print "żółć"
...twój program prześle na wyjście ciąg bajtów, będący napisem "żółć"
zakodowanym kodowaniem utf-8 (0xc5, 0xbc, 0xc3, 0xb3, 0xc5, 0x82, 0xc4,
0x87)
Natpmiast, jeżeli Twój edytor jest ustawiony na iso-8859-2 i napiszesz:
# -*- coding: iso-8859-2 -*-
print "żółć"
...twój program prześle na wyjście ciąg bajtów, będący napisem "żółć"
zakodowanym kodowaniem iso-8859-2 (0xbf, 0xf3, 0xb3, 0xe6).
Oczywiście, tak jak napisałem wyżej, terminal/wiersz poleceń/środowisko
programistyczne, pod którym uruchamiasz program wypisze właściwe znaki
tylko wtedy jeżeli skonfigurowane jest pod takie a nie inne kodowanie.
Czyżby stworzenie programu uruchamialnego na różnych maszynach jest
skomplikowane i wymaga czegoś jak poniżej?
# -*- coding: iso-8859-2 -*-
kodowanie = raw_inpit('Podaj kodowanie Twojego srodowiska:')
print "żółć".decode('iso-8859-2').encode(kodowanie)
Na szczęście Python sam stara się dowiedzieć, jakiego kodowania
używa środowisko (terminal, wiersz poleceń bądź IDE czyli środowisko
programistyczne takie jak SPE...) w którym został uruchomiony --
informację tę można pobrać z sys.stdout.encoding, np.
# -*- coding: iso-8859-2 -*-
import sys
print "żółć".decode('iso-8859-2').encode(sys.stdout.encoding)
Ale nie dość na tym. print jest na tyle mądre, że jeżeli podamy mu
obiekt unicode, a nie str, zakoduje ten obiekt kodowaniem takim,
jakie jest w sys.stdout.encoding -- a więc możemy napisać:
# -*- coding: iso-8859-2 -*-
print "żółć".decode('iso-8859-2') # przekazujemy obiekt unicode
Przy czym -- to osobna sprawa, ale warto ją zauważyć i stosować gdzie
się da -- zamiast tworzyć obiekt str (z str-owego literału "żółć")
i następnie go dekodować do postaci unicode za pomocą kodowania jakim
kodowane są źródłą naszego programu -- możemy od razu utworzyć obiekt
unicode (z unicodowego literału u"żółć"):
Mówiąc bardziej ogólnie:
# -*- coding: JAKIES_KODOWANIE_ZRODEL -*-
.......
....... "żółć".decode(JAKIES_KODOWANIE_ZRODEL) .......
.......
jest równoznaczne z:
# -*- coding: JAKIES_KODOWANIE_ZRODEL -*-
.......
....... u"żółć" .......
.......
A wracając do naszego przykładu:
# -*- coding: iso-8859-2 -*-
print u"żółć"
Przekaże na wyjśćie ciąg bajtów będącym napisem "żółć" zakodowanym
takim kodowaniem, jakie Python wykrył i zapisał w sys.stdout.encoding.
Oczywiście może się zdarzyć, że w sys.stdout.encoding znajdzie się
kodowanie nie obsługujące podanych znaków -- np. gdy standardowe wyjście
przekierowano do pliku (sys.stdout.encoding zawiera wówczas kodowanie
ascii); powyższy kod zwróci wówczas błąd:
UnicodeEncodeError: 'ascii' codec can't encode characters in position
0-3: ordinal not in range(128)
Więc w programach, które nie są prostymi skryptami czy programikami
do użytku własnego i znajomych, można dać np.:
# -*- coding: iso-8859-2 -*-
try:
print u"żółć"
except UnicodeEncodeError:
print u"żółć".encode(errors=ignore)
# ewentualnie: print u"żółć".encode('unicode_escape')
lub nawet:
# -*- coding: iso-8859-2 -*-
import locale
KODOWANIE_Z_LOCALE = locale.getpreferredencoding()
try:
print u"żółć"
except UnicodeEncodeError:
print u"żółć".encode(KODOWANIE_Z_LOCALE, errors=ignore)
> ========================
> print unicode("Gotówka wysłane",'utf-8') odszyfrowanie do unicode stringu
> zaszyfrowanego UTF-8
> ^
> SyntaxError: invalid syntax
> Script terminated.
> ========================
[w związku z pytaniem 3]
Przypuszczam, że:
* albo zapomniałeś, by przed komentarzem "odszyfrowanie do unicode
stringu..." dać znacznik komentarza #
* albo uruchomiłeś Pythona 3.x, który nie ma słowa kluczowego print, ma
natomiast funkcję print() (pierwsza rzucająca się w oczy różnica, jest
taka, że zawsze trzeba używać nawiasów)
* albo zadeklarowane kodowanie źródeł programu jest niezgodnie z
kodowaniem faktycznie używanym przez edytor, pod którym pisałeś kod
(nie sądzę, żeby to było to, ale teoretycznie w pewnych sytuacjach też
może to spowodować błąd składniowy).
> PYTANIE 5
> W którymś poście na grupie pojawia zapis:
> sys.setdefaultencoding('utf8')
> czyli coś o czym wcześniej nie czytałem. i pytanie co robi ten kod?
W 99% przypadków nie należy tego ruszać (zresztą celowo jest to
utrudnione -- poprzez usuwanie tej funkcji z modułu sys zaraz po
pierwszym jej użyciu w module site...).
Funkcja ta ustawia tzw. domyślne kodowanie Pythona -- dla sytuacji,
w których programista nie określił, jakie kodowanie ma być użyte do
zakodowania/rozkodowania... Np. jeżeli użyjemy encode()/decode()
bez podawania kodowania, lub jeżeli (jest wiele takich sytuacji)
Python dostał unicode, a spodziewał się str, lub jeżeli dostał str, a
spodziewał się unicode -- sam niejawnie rozkodowuje/zakodowuje dane
by uzyskać właściwy typ; używa wtedy owego domyślnego kodowania.
Domyślne kodowanie jest standardowo ustawione na ascii (obejmje
tylko najbardziej standardowe 128 znaków: alfabet łaciński,
podstawowe znaki matematyczne i przestankowe, podstawowe kody
kontrolne, np. znak końca wiersza...), co oznacza, że np. kod:
u"żółć".encode()
...spowoduje wystąpienie wyjątku UnicodeEncodeError.
----
Na koniec kilka morałów:
* w odniesieniu do tekstu -- wszędzie gdzie się da, należy używać
obiektów unicode a nie str, a jedynie na wejściu/wyjściu
odkodowywać/zakodowywać z/do postaci ciągu bajtów (str),
* na dłuższą metę lepiej podawać kodowanie jawnie ("explicit is
better than implicit" -- Zen of Python) i raczej unikać sytuacji,
w których Python będzie dokonywać automatycznego-niejawnego
kodowania/dekodowania (bo gdy wyskoczy błąd związany z kodowaniem,
często trudno potem dojść, gdzie tak naprawdę nastąpiło
zniekształcenie danych...).
Pozdrawiam,
Jan Kaliszewski (zuo)
PS. UWAGA: cała moja odpowiedź dotyczy Pythona 2.x. W Pythonie 3.x
rzeczy wyglądają trochę inaczej: dawny typ unicode nazywa się str,
a dawnego str nie ma. Jest za to typ bytes (i pokrewny mu bytearray...),
do pewnego stopnia podobny do dawnego str, ale nieprzeznaczony do
operowania danymi tekstowymi, a jedynie binarnymi (ale to inna historia).
W Pythonie 3.x nie ma też niejawnego automatycznego kodowania/dekodowania
-- doświadczenia Pythona 2.x pokazują, że sprawiało ono wiele kłopotów.
W Pythonie 3.x programista, jeżeli poda dane złego typu otrzyma jasny
komunikat błędu, a nie nieprawidłowe wyniki zmuszające do bawienia się
w Sherlocka Holmesa ("w którym momencie Python dokonał tego niejawnego
kodowania/dekodowania?").
--
Jan Kaliszewski (zuo)
-- chodziło mi o zobrazowanie tego, że stosowanie literałów unikodowych
(z literą u przed cudzysłowem, np. u"żółć" czy u'jaźń') uniezależnia
wartość
tak tworzonej zmiennej napisowej od tego, jakie jest kodowanie źródeł
programu.
Wszystkie poniższe fragmenty kodu przypiszą zmiennej `a` *identyczną*
zawartość:
# coding: utf-8
a = u"jaźń"
for element in a:
print ord(element)
# ^ wypisano 4 wartości (unikodowe code point'y): 106, 96, 378, 324
# coding: iso-8859-2
a = u"jaźń"
for element in a:
print ord(element)
# ^ wypisano 4 wartości (unikodowe code point'y): 106, 96, 378, 324
# coding: cp1250
a = u"jaźń"
for element in a:
print ord(element)
# ^ wypisano 4 wartości (unikodowe code point'y): 106, 96, 378, 324
Natomiast każdy z poniższych przypisze zmiennej `a` *inną* zawartość:
# coding: utf-8
a = u"jaźń"
for element in a:
print ord(element)
# wypisano 6 liczb: 106, 96, 197, 186, 197, 132
# coding: iso-8859-2
a = u"jaźń"
for element in a:
print ord(element)
# wypisano 4 liczby: 106, 96, 188, 241
# coding: cp1250
a = u"jaźń"
for element in a:
print ord(element)
# wypisano 4 liczby: 106, 96, 159, 241
--
Jan Kaliszewski (zuo)
# coding: utf-8
a = "jaźń"
for element in a:
print ord(element)
# wypisano 6 liczb: 106, 96, 197, 186, 197, 132
# coding: iso-8859-2
a = "jaźń"
for element in a:
print ord(element)
# wypisano 4 liczby: 106, 96, 188, 241
# coding: cp1250
a = "jaźń"
Fajnie by było, gdyby to było takie proste... sys.stdout.encoding
zawiera kodowanie tylko wtedy, kiedy stdout jest rzeczywiście
w użyciu. Jeśli wyjście jest przekierowane, zawiera None,
co spowoduje, że w tym skrypcie:
> # -*- coding: iso-8859-2 -*-
> import sys
> print "żółć".decode('iso-8859-2').encode(sys.stdout.encoding)
Wystąpi wyjątek TypeError: encode() argument 1 must be string, not None.
> Ale nie dość na tym. print jest na tyle mądre, że jeżeli podamy mu
> obiekt unicode, a nie str, zakoduje ten obiekt kodowaniem takim,
> jakie jest w sys.stdout.encoding
J.w., czyli tylko w przypadku braku przekierowania stdout.
Po przekierowaniu użyte będzie kodowanie domyślne, czyli to
zwracane przez sys.getdefaultencoding().
> Przy czym -- to osobna sprawa, ale warto ją zauważyć i stosować gdzie
> się da -- zamiast tworzyć obiekt str (z str-owego literału "żółć")
> i następnie go dekodować do postaci unicode za pomocą kodowania jakim
> kodowane są źródłą naszego programu -- możemy od razu utworzyć obiekt
> unicode (z unicodowego literału u"żółć"):
Popieram. :-)
> Oczywiście może się zdarzyć, że w sys.stdout.encoding znajdzie się
> kodowanie nie obsługujące podanych znaków --
Oczywiście...
> np. gdy standardowe wyjście
> przekierowano do pliku (sys.stdout.encoding zawiera wówczas kodowanie
> ascii)
ale przykład niedobry... sys.stdout.encoding zawiera wówczas None.
> Więc w programach, które nie są prostymi skryptami czy programikami
> do użytku własnego i znajomych, można dać np.:
>
> # -*- coding: iso-8859-2 -*-
> try:
> print u"żółć"
> except UnicodeEncodeError:
> print u"żółć".encode(errors=ignore)
> # ewentualnie: print u"żółć".encode('unicode_escape')
>
> lub nawet:
>
> # -*- coding: iso-8859-2 -*-
> import locale
> KODOWANIE_Z_LOCALE = locale.getpreferredencoding()
>
> try:
> print u"żółć"
> except UnicodeEncodeError:
> print u"żółć".encode(KODOWANIE_Z_LOCALE, errors=ignore)
>
Sam zwykle stosuję to drugie, ale pamiętając o tym, że np. w Windows
domyślnie kodowanie w okienku poleceń (cmd) i w samym systemie są
różne, co można łatwo sprawdzić wykonując skrypt:
#coding:utf-8
import locale, sys
print "preferred encoding is", locale.getpreferredencoding()
print "default encoding is", sys.getdefaultencoding()
print "stdout encoding is", sys.stdout.encoding
Bez przekierowania otrzymujemy np. taki wynik:
preferred encoding is cp1250
default encoding is ascii
stdout encoding is cp852
a z przekierowaniem taki:
preferred encoding is cp1250
default encoding is ascii
stdout encoding is None
Normalnie więc koduję zawartością sys.stdout.encoding, a jeśli
jest nieokreślona (None) używam albo locale.getpreferredencoding(),
albo jakiegoś z góry określonego (najczęściej UTF-8).
--
mrg
> On 2010-06-18 20:36, Jan Kaliszewski wrote:
>> Na szczęście Python sam stara się dowiedzieć, jakiego kodowania
>> używa środowisko (terminal, wiersz poleceń bądź IDE czyli środowisko
>> programistyczne takie jak SPE...) w którym został uruchomiony --
>> informację tę można pobrać z sys.stdout.encoding
>
> Fajnie by było, gdyby to było takie proste... sys.stdout.encoding
> zawiera kodowanie tylko wtedy, kiedy stdout jest rzeczywiście
> w użyciu. Jeśli wyjście jest przekierowane, zawiera None,
> co spowoduje, że w tym skrypcie:
>
>> # -*- coding: iso-8859-2 -*-
>> import sys
>> print "żółć".decode('iso-8859-2').encode(sys.stdout.encoding)
>
> Wystąpi wyjątek TypeError: encode() argument 1 must be string, not None.
Ups, faktycznie.
>> np. gdy standardowe wyjście
>> przekierowano do pliku (sys.stdout.encoding zawiera wówczas kodowanie
>> ascii)
>
> ale przykład niedobry... sys.stdout.encoding zawiera wówczas None.
jw.
--
Jan Kaliszewski (zuo)
Witam
dzięki za wyjaśnienia Twoje i p. Jana Kaliszewskiego.
Twoja wypowiedź jest prawie poprawnym wyjasnieniem niuansów, z któych część
w międzyczasie zauważyłem:
np to że jak robię przekierowanie ( | lub > , >>) to zmienia się kodowanie
na None.
Ale Twoja wypowiedź jak i poprzednika nie wyjaśniła WPROST czemu ten sam
skrypt, uruchomiony w ten sam sposób na tym samym komputerze u jednego
użytkownika działa tak, a u drugiego inaczej.
W Twoim opisie powyżej napisałeś wprost jakie są kodowania w zależności od
kontekstu i w zależności czy jest przekierowanie czy nie. A moje
doświadczenie sugeruje, że nie jest to stałe (zmienia w zależności od
użytkownika i zastanawia mnie która opcja systemowa za to odpowiada).
Ja jeszcze przed Waszą odpowiedzią robiłem tak:
encoding=stdout.encoding
#if encoding==None: encoding='CP852'
#if encoding==None: encoding='CP1250'
if encoding==None: encoding='ISO-8859-2'
# a potem kodowałem do powyższego kodu z tekstu w formacie unicode.
Tzn brałem encoding, a gdy gdy było puste to ustawiałem jakieś na próbę.
W wyniku testów wyszło mi że w przypadku przekierowania 'ISO-8859-2' na 3
osobach było prawie OK, tzn niepoprawnie wyświetla litera ś.
Mając teraz Wasze wyjaśnienia postaram spróbować zrobić kod działający
zawsze.
O wynikach poinformuję jeżeli kogoś to zaintersuje, natomiast jest jeszcze
jedno 2 pytania w tym kontekście.
1.
Czy w przypadku Pythona 3.0 ten problem (różne kodowanie w zależności od
uruchomienia kontekstu oraz w zależności czy jest przekierowanie) został
rozwiązany? Mógłbym zrobić test, ale mogą być specyficzne wyniki, więc skoro
się na tym znasz to wolę zapytać, no i ja musiałbym zainstalować ponownie
3.0, a już odinstalowałem.
2
Czy ktoś kto korzystał z PyScripter może tam używać polskich znaczków?
Uruchamiałem ten program na 2 komputerach i okazało się, że nie mogę użyć
tam polskich znaczków. Tzn przełączają mi się pozycje w lewym okienku. Nie
wiem czy możliwe, by ktoś wypuścił tak wadliwy edytor, czy też znowu
działają jakieś lokalne ustawienia powodujące, że PyScripter staje się
bezużytecznym edytorem dla kogoś uzywającego polskich znaczków.
Zwykle są dwie takie "opcje" - użytkownik może sobie ustawić kodowanie
wejścia i wyjścia, a często również czcionkę (która musi zawierać
literki tak samo zakodowane - inaczej na ekranie widzi "śmieci")
- w zasadzie Jan już to napisał...
W WinXP, w oknie CMD możesz zmienić kodowanie poleceniem chcp,
a czcionkę we właściwościach okna CMD. Z mojego doświadczenia
wynika, że mało kto zna, a jeszcze mniej używa chcp, więc to,
że u jednego użytkownika ten sam program "działał inaczej", niż
u innego wynika na 99,99% z zastosowania przez jednego czcionki
o innym kodowaniu (np. 1250), niż drugi (np. 852).
> W wyniku testów wyszło mi że w przypadku przekierowania 'ISO-8859-2' na 3
> osobach było prawie OK, tzn niepoprawnie wyświetla litera ś.
Dam głowę, że w użyciu była czcionka z pliterkami kodowanymi w 1250,
a "prawie OK" było dlatego, że polskie literki w CP1250 i ISO-8859-2
są kodowane "prawie tak samo" - różne są tylko kody 3 z 9 (6 z 18 jeśli
uwzględnić wielkie): ą, ś i ź.
> Czy w przypadku Pythona 3.0 ten problem (różne kodowanie w zależności od
> uruchomienia kontekstu oraz w zależności czy jest przekierowanie) został
> rozwiązany? Mógłbym zrobić test, ale mogą być specyficzne wyniki, więc skoro
> się na tym znasz to wolę zapytać, no i ja musiałbym zainstalować ponownie
> 3.0, a już odinstalowałem.
Nie testowałem i też jeszcze nie używam Python-a 3, ale wg mnie pod
tym względem nic się nie zmieniło - to, jakiego kodowania i czcionki
używa dany użytkownik jest jakby od Python-a niezależne, więc chyba
trudno to nazwać "problemem do rozwiązania" w Python-ie... ;-)
--
mrg
W nowszych Pytongach unicode jest domyślne, o ile dobrze pamiętam.
Waldek
To mocno nieścisłe stwierdzenie. W tym wypadku "w nowszych" == Python 3.x
A domyślne jest w tym sensie, że:
* podstawowy typ napisowy to 'str' -- z tym, że jest to ten typ, który
w Py 2.x nazywał się 'unicode' (tak jak już napisałem w którymś z postów
'str' z Py 2.x zostało usunięte; w jego miejsce pojawia się typ bytes,
który, zasadniczo przeznaczony do danych binarnych a nie tekstowych);
Z tego, że standardowe stringi są unicodowe, wynika w Pythonie 3.x również
to, że nie są już używane literały z 'u' przed cudzysłowem.
* domyślnym kodowaniem źródeł jest utf-8 (a nie ascii, jak w 2.x); co
fajne, nazwy zmiennych (pythonowe identyfikatory) mogą zawierać dowolne
litery unicodowe -- nie tylko łacińskie, a więc zmienna może się nazywać
np. 'żółw' lub 'бабушка'.
* kodowanie domyślne zwracane przez sys.getdefaultencoding() wydaje się
być również ustawione na 'utf-8' a nie 'ascii' jak w Py 2.x; przynajmniej
tak jest u mnie (Debian testing) -- w dokumentacji Pythona nie widzę nic
o tym, czy jest to zawsze 'utf-8'; to ustawienie ma co prawda i tak ma
znacznie mniejsze znaczenie, niż w Py 2.x, bo w Py 3.x nie ma niejawnej
automatycznej konwersji str <-> bytes (kodowanie z
sys.getdefaultencoding() było w Py 2.x stosowane przy niejawnej
automatycznej konwersji unicode <-> str).
pozdr.
*j