Krzaki
Daniel Mróz - 24-12-2006 00:59
Krzaki
Cześć
>>> niekrzaki = 'Zazolc gesla jazn' >>> krzaki = 'Zażółć gęślą jaźń' >>> len(niekrzaki) 17 >>> len(krzaki) 26
Jakie czary trzeba odprawić, żeby znaki wielobajtowe traktował jak jednobajtowe? Zależy mi na tym, aby len() w drugim przypadku zwracało liczbę 17, a nie 26. Wiem, że można tak:
>>> len(u'Zażółć gęślą jaźń') 17
ale ja stringa mam w zmiennej. Potrzebowałbym zatem jakiejś funkcji typu u(krzaki). Wolałbym także uniknąć combosów w rodzaju krzaki.decode('utf8').encode('iso8859-2') z przyczyn wiadomych.
Pozdrawiam Beorn
-- Daniel 'Beorn' Mróz <beorn@alpha.pl> http://127.0.0.1/beorn [GIT d s:- a-@ C++++ UL++++$ P+ L++++ E--- W+ N+++ o? K- w---] [O- M- V! PS+ PE++ Y+ PGP++ t- 5 X R !tv b+ DI D++ G++ e h*] [ r(-) y+ ]
Amadeusz Jasak - 24-12-2006 00:59
Daniel Mróz napisał(a): > Cześć > > >>>> niekrzaki = 'Zazolc gesla jazn' >>>> krzaki = 'Zażółć gęślą jaźń' >>>> len(niekrzaki) > 17 >>>> len(krzaki) > 26 > > > Jakie czary trzeba odprawić, żeby znaki wielobajtowe traktował jak > jednobajtowe? Zależy mi na tym, aby len() w drugim przypadku zwracało > liczbę 17, a nie 26. > Wiem, że można tak: > >>>> len(u'Zażółć gęślą jaźń') > 17 > > > ale ja stringa mam w zmiennej. Potrzebowałbym zatem jakiejś funkcji > typu u(krzaki). Wolałbym także uniknąć combosów w rodzaju > krzaki.decode('utf8').encode('iso8859-2') z przyczyn wiadomych. > > > Pozdrawiam > Beorn > U mnie na Pythonie 2.5 pod windą jest: >>> krzaki = 'Zażółć gęślą jaźń' >>> niekrzaki = 'Zazolc gesla jazn' >>> print 'OK' if len(krzaki) == len(niekrzaki) else 'Nie OK' OK
-- Pozdrawiam Amadeusz Jasak vel alfanick
Jarek Zgoda - 24-12-2006 00:59
Daniel Mróz napisał(a):
> ale ja stringa mam w zmiennej. Potrzebowałbym zatem jakiejś funkcji > typu u(krzaki). Wolałbym także uniknąć combosów w rodzaju > krzaki.decode('utf8').encode('iso8859-2') z przyczyn wiadomych.
To jest dobry sposób, co Ci się w nim nie podoba? Inaczej mówiąc - przyczyny nie są wiadome, wyjaśnij je.
-- Jarek Zgoda http://jpa.berlios.de/
Jacek Konieczny - 24-12-2006 00:59
On 2006-12-14, Daniel Mróz <beorn@alpha.pl> wrote: > Cześć > > >>>> niekrzaki = 'Zazolc gesla jazn' >>>> krzaki = 'Zażółć gęślą jaźń' >>>> len(niekrzaki) > 17 >>>> len(krzaki) > 26 > > > Jakie czary trzeba odprawić, żeby znaki wielobajtowe traktował jak > jednobajtowe? Zależy mi na tym, aby len() w drugim przypadku zwracało > liczbę 17, a nie 26. > Wiem, że można tak: > >>>> len(u'Zażółć gęślą jaźń') > 17 > > > ale ja stringa mam w zmiennej. Potrzebowałbym zatem jakiejś funkcji > typu u(krzaki). Wolałbym także uniknąć combosów w rodzaju > krzaki.decode('utf8').encode('iso8859-2') z przyczyn wiadomych. > > > Pozdrawiam > Beorn >
Daniel Mróz - 24-12-2006 00:59
Dnia Thu, 14 Dec 2006 20:07:53 +0100 Amadeusz Jasak <amadeusz.jasak@gmail.com> napisał(a): > U mnie na Pythonie 2.5 pod windą jest: > >>> krzaki = 'Zażółć gęślą jaźń' > >>> niekrzaki = 'Zazolc gesla jazn' > >>> print 'OK' if len(krzaki) == len(niekrzaki) else 'Nie OK' > OK Pod 2.4 niestety jest inaczej :(
Pozdrawiam Beorn
-- Daniel 'Beorn' Mróz <beorn@alpha.pl> http://127.0.0.1/beorn [GIT d s:- a-@ C++++ UL++++$ P+ L++++ E--- W+ N+++ o? K- w---] [O- M- V! PS+ PE++ Y+ PGP++ t- 5 X R !tv b+ DI D++ G++ e h*] [ r(-) y+ ]
Daniel Mróz - 24-12-2006 00:59
Dnia Thu, 14 Dec 2006 21:26:16 +0100 Jarek Zgoda <jzgoda@o2.usun.pl> napisał(a): > > ale ja stringa mam w zmiennej. Potrzebowałbym zatem jakiejś funkcji > > typu u(krzaki). Wolałbym także uniknąć combosów w rodzaju > > krzaki.decode('utf8').encode('iso8859-2') z przyczyn wiadomych. > To jest dobry sposób, co Ci się w nim nie podoba? Inaczej mówiąc - > przyczyny nie są wiadome, wyjaśnij je. 1. to jest straszna rzeźba żeby przeprowadzać konwersje w celu sprawdzenia długości łańcucha, 2. bez sensu, 3. nie wiem w jakim kodowaniu będzie string (równie dobrze może to być cyrylica, szwedzki, amharski lub klingoński)
Pozdrawiam Beorn
-- Daniel 'Beorn' Mróz <beorn@alpha.pl> http://127.0.0.1/beorn [GIT d s:- a-@ C++++ UL++++$ P+ L++++ E--- W+ N+++ o? K- w---] [O- M- V! PS+ PE++ Y+ PGP++ t- 5 X R !tv b+ DI D++ G++ e h*] [ r(-) y+ ]
mime - 24-12-2006 00:59
> >>>> niekrzaki = 'Zazolc gesla jazn' >>>> krzaki = 'Zażółć gęślą jaźń' >>>> len(niekrzaki) > 17 >>>> len(krzaki) > 26 > > > Jakie czary trzeba odprawić, żeby znaki wielobajtowe traktował jak > jednobajtowe? Zależy mi na tym, aby len() w drugim przypadku zwracało > liczbę 17, a nie 26. > Wiem, że można tak: > >>>> len(u'Zażółć gęślą jaźń') > 17 > > > ale ja stringa mam w zmiennej. Potrzebowałbym zatem jakiejś funkcji > typu u(krzaki). Wolałbym także uniknąć combosów w rodzaju > krzaki.decode('utf8').encode('iso8859-2') z przyczyn wiadomych. >
w pythonie to ja swiezynka jestem, ale sam bylem ciekaw jak to dziala wiec wygoglalem: http://evanjones.ca/python-utf8.html
pzdr mime
Jacek Konieczny - 24-12-2006 00:59
On 2006-12-15, Daniel Mróz <beorn@alpha.pl> wrote: > Dnia Thu, 14 Dec 2006 21:26:16 +0100 > Jarek Zgoda <jzgoda@o2.usun.pl> napisał(a): >> > ale ja stringa mam w zmiennej. Potrzebowałbym zatem jakiejś funkcji >> > typu u(krzaki). Wolałbym także uniknąć combosów w rodzaju >> > krzaki.decode('utf8').encode('iso8859-2') z przyczyn wiadomych. >> To jest dobry sposób, co Ci się w nim nie podoba? Inaczej mówiąc - >> przyczyny nie są wiadome, wyjaśnij je. > 1. to jest straszna rzeźba żeby przeprowadzać konwersje w celu > sprawdzenia długości łańcucha,
Jeśli interesuje Ciebie ilość znaków, a nie bajtów, to normalne, że operujesz na Unicode.
I rzadko będzie to krzaki.decode('utf8').encode('iso8859-2'). Raczej:
krzaki = jakies_dane_wejściowe.decode(kodowanie_wejścia)
.... całe przetwarzanie w programie ...
wyjście(krzaki.encode(kodowanie_wyjścia))
A w wielu przypadkach nawet nie, bo wejście i wyjście będą już strumieniami/obiektami, które dostarczają/pobierają Unicode (np. pliki otwarte przez codecs.open()).
Jeśli operujesz na tekstach, to naucz się używać do tego obiektów Unicode. Stringi to tylko forma przejściowa do wejścia/wyjścia, które operuje na bajtach.
Czasami oczywiście można dane tekstowe traktowąć jako bajty, nieprzejmować się kodowaniem itd. (np. jeśli chcesz zakodować odpowiednik seda), ale trzeba zdawać sobie sprawę z ograniczeń (coś co wygląda jak "ą" to może być jeden bajt, albo dwa, zależnie od kodowania i len(string) nie poda liczby znaków).
> 2. bez sensu, > 3. nie wiem w jakim kodowaniu będzie string (równie dobrze może to być > cyrylica, szwedzki, amharski lub klingoński)
Dostajesz ciąg bajtów, wiesz, że to tekst, nie wiesz jak został zakodowany i chcesz się dowiedzieć ile tam jest znaków? Tak się nie da.
Pozdrowienia, Jacek
Jacek Konieczny - 24-12-2006 00:59
On 2006-12-15, Daniel Mróz <beorn@alpha.pl> wrote: > Dnia Thu, 14 Dec 2006 20:07:53 +0100 > Amadeusz Jasak <amadeusz.jasak@gmail.com> napisał(a): >> U mnie na Pythonie 2.5 pod windą jest: >> >>> krzaki = 'Zażółć gęślą jaźń' >> >>> niekrzaki = 'Zazolc gesla jazn' >> >>> print 'OK' if len(krzaki) == len(niekrzaki) else 'Nie OK' >> OK > Pod 2.4 niestety jest inaczej :(
Nieprawda. Inaczej jest jak się używa innego kodowania na terminalu lub w pliku w którym ten kod wpiszesz. Wersja pythona nie ma nic do rzeczy.
'Zażółć gęślą jaźń' to tylko ciąg bajtów, a jakich, to zależy od kodowania używanego podczas jego parsowania.
Jeśli interesuje nas ciąg znaków, to powinno być: u'Zażółć gęślą jaźń', a na początku pliku powinna być deklaracja kodowania.
Pozdrowienia, Jacek
Jaroslaw Zabiello - 24-12-2006 00:59
Dnia Fri, 15 Dec 2006 10:29:22 +0100, Daniel Mróz napisał(a):
> 3. nie wiem w jakim kodowaniu będzie string (równie dobrze może to być > cyrylica, szwedzki, amharski lub klingoński)
Dlatego nie powinieneś w ogóle pracować na stringach ale na pythonowych obiektach unikodowych. Wtedy zawsze będziesz miał poprawną odpowiedź z metody len. Efektem ubocznym tego jest także to, że print wywali ci poprawne znaki bez względu na to czy to konsola DOS, Linuksa czy okno windozy.
-- Jarosław Zabiełło http://blog.zabiello.com
William - 24-12-2006 00:59
Jaroslaw Zabiello napisał(a): > Dnia Fri, 15 Dec 2006 10:29:22 +0100, Daniel Mróz napisał(a): > >> 3. nie wiem w jakim kodowaniu będzie string (równie dobrze może to być >> cyrylica, szwedzki, amharski lub klingoński) > > Dlatego nie powinieneś w ogóle pracować na stringach ale na pythonowych > obiektach unikodowych. Wtedy zawsze będziesz miał poprawną odpowiedź z > metody len. Efektem ubocznym tego jest także to, że print wywali ci > poprawne znaki bez względu na to czy to konsola DOS, Linuksa czy okno > windozy. >
Więcej, powinieneś zawsze uruchamiać pythona z przełącznikiem -U :) BTW czy można to gdzieś wymusić w jakimś pliku konfiguracyjnym ?
Rob Wolfe - 26-12-2006 00:30
Daniel Mróz <beorn@alpha.pl> writes:
> Dnia Thu, 14 Dec 2006 21:26:16 +0100 > Jarek Zgoda <jzgoda@o2.usun.pl> napisał(a): >> > ale ja stringa mam w zmiennej. Potrzebowałbym zatem jakiejś funkcji >> > typu u(krzaki). Wolałbym także uniknąć combosów w rodzaju >> > krzaki.decode('utf8').encode('iso8859-2') z przyczyn wiadomych. >> To jest dobry sposób, co Ci się w nim nie podoba? Inaczej mówiąc - >> przyczyny nie są wiadome, wyjaśnij je. > 1. to jest straszna rzeźba żeby przeprowadzać konwersje w celu > sprawdzenia długości łańcucha,
Konwersja jest konieczna, aby z bajtów skonstruować znaki. Nie ma innej drogi.
> 2. bez sensu,
No to zobacz to:
1. >>> "ł" '\xb3' >>> "ó".decode("iso-8859-2").encode("utf-8") '\xc3\xb3'
Dostajesz na wejściu bajt o kodzie 0xb3. W jaki sposób odgadniesz, czy jest to znak "ł" czy składowa znaku "ó" bez poznania kodowania?
> 3. nie wiem w jakim kodowaniu będzie string (równie dobrze może to być > cyrylica, szwedzki, amharski lub klingoński)
Aby poznać liczbę znaków w jakimś strumieniu bajtów *musisz* znać wejściowe kodowanie.
-- pozdrawiam Rob
beorn@alpha.pl - 28-12-2006 00:13
Rob Wolfe writes: >> 1. to jest straszna rzeźba żeby przeprowadzać konwersje w celu >> sprawdzenia długości łańcucha, > Konwersja jest konieczna, aby z bajtów skonstruować znaki. > Nie ma innej drogi. Dlaczego nie?
>> 2. bez sensu, > No to zobacz to: [âŚ] > Dostajesz na wejściu bajt o kodzie 0xb3. > W jaki sposób odgadniesz, czy jest to znak "ł" > czy składowa znaku "ó" bez poznania kodowania? Ale kodowanie jest znane i zapisane w locale. Chodzi mi o to, czy jest funkcja lub sposób sprawdzenia długości ciągu niezależnie od kodowania, bez samodzielnej implementacji mapowania wartości locale na kodowania i przekodowywania.
>> 3. nie wiem w jakim kodowaniu będzie string (równie dobrze może to być >> cyrylica, szwedzki, amharski lub klingoński) > Aby poznać liczbę znaków w jakimś strumieniu bajtów > *musisz* znać wejściowe kodowanie. I tę informację można wywnioskować z wartości zmiennych środowiskowych LC_*. Po Pythonie, który ma podobno świetną obsługę unicode, spodziewałem się, że takie pierdoły będzie miał "w standardzie".
Pozdrawiam Beorn
-- Sygnatura w remoncie
Rob Wolfe - 28-12-2006 00:13
beorn@alpha.pl writes:
> Rob Wolfe writes: >>> 1. to jest straszna rzeźba żeby przeprowadzać konwersje w celu >>> sprawdzenia długości łańcucha, >> Konwersja jest konieczna, aby z bajtów skonstruować znaki. >> Nie ma innej drogi. > Dlaczego nie?
String w Pythonie jest sekwencją 8-bitowych znaków, a zatem wykonanie funkcji `len` na tej sekwencji musi zwrócić liczbę bajtów, czyż nie?
>>> 2. bez sensu, >> No to zobacz to: > [âŚ] >> Dostajesz na wejściu bajt o kodzie 0xb3. >> W jaki sposób odgadniesz, czy jest to znak "ł" >> czy składowa znaku "ó" bez poznania kodowania? > Ale kodowanie jest znane i zapisane w locale. Chodzi mi o to, czy jest > funkcja lub sposób sprawdzenia długości ciągu niezależnie od > kodowania, bez samodzielnej implementacji mapowania wartości locale na > kodowania i przekodowywania.
Co rozumiesz przez `długość ciągu`? Dla obiektu string jest to zawsze liczba bajtów. Dla obiektu unicode jest to zasze liczba znaków. Masz jakąś inną definicję?
>>> 3. nie wiem w jakim kodowaniu będzie string (równie dobrze może to być >>> cyrylica, szwedzki, amharski lub klingoński) >> Aby poznać liczbę znaków w jakimś strumieniu bajtów >> *musisz* znać wejściowe kodowanie. > I tę informację można wywnioskować z wartości zmiennych środowiskowych > LC_*. Po Pythonie, który ma podobno świetną obsługę unicode, > spodziewałem się, że takie pierdoły będzie miał "w standardzie".
Chyba nie rozumiem czego oczekujesz. Chciałbyś aby funkcja `len` zwracała liczbę znaków stringa, a nie faktyczną ilość bajtów? A co gdy mam pole w bazie o długości 20 znaków (bajtów) i taki kod:
>>> krzaki = "zażółć gęślą jaźń".decode("iso-8859-2").encode("utf-8") >>> len(krzaki) 26 >>> if len(krzaki) <= 20: .... <zapis do bazy>
Wg Twojej koncepcji funkcja `len` w tym przypadku powinna zwrócić 17 i biedny programista byłby święcie przekonany, że zapis do bazy jest OK, podczas gdy 6 bajtów zostałoby obciętych.
To mi trochę przypomina wątek na comp.lang.python, gdzie koleś koniecznie chciał znać liczbę bajtów obiektu unicode bez użycia konkretnego kodowania. W przypadku stringów mówimy zawsze o bajtach, a w przypadku unicodu zawsze o znakach. Gdy potrzebujesz liczby znaków w stringu lub liczby bajtów w unicode to jest to przypadek szczególny (IMHO niewart wprowadzania nowej funkcji do języka) i dokonujesz konwersji. (nawiasem mówiąc napisanie własnej funkcji do liczenia ilości znaków jest przecież trywialne).
-- pozdrawiam Rob
beorn@alpha.pl - 29-12-2006 00:25
Rob Wolfe writes: >>>> 1. to jest straszna rzeźba żeby przeprowadzać konwersje w celu >>>> sprawdzenia długości łańcucha, >>> Konwersja jest konieczna, aby z bajtów skonstruować znaki. >>> Nie ma innej drogi. >> Dlaczego nie? > String w Pythonie jest sekwencją 8-bitowych znaków, a zatem > wykonanie funkcji `len` na tej sekwencji musi zwrócić liczbę > bajtów, czyż nie? No właśnie. Spodziewałem się, że skoro w nagłówku skryptu zdefiniowałem kodowanie jako Unicode, to Python wszystkie ciągi znaków będzie traktował jako wielobajtowe z uwzględnieniem systemowego ustawienia locale.
>> funkcja lub sposób sprawdzenia długości ciągu niezależnie od >> kodowania, bez samodzielnej implementacji mapowania wartości locale na >> kodowania i przekodowywania. > Co rozumiesz przez `długość ciągu`? Długość ciągu w znakach wielobajtowych.
> Dla obiektu string jest to zawsze liczba bajtów. > Dla obiektu unicode jest to zasze liczba znaków. OK, tylko że ponownie przytoczę mój test:
------------------------------ #!/usr/bin/python # -*- coding: utf8 -*-
print len(unicode('Zażółć gęślą jaźń')) [beorn@rei ~]$ python -OO test.py Traceback (most recent call last): File "test.py", line 4, in ? print len(unicode('Zażółć gęślą jaźń')) UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 2: ordinal not in range(128) ------------------------------
>>> Aby poznać liczbę znaków w jakimś strumieniu bajtów >>> *musisz* znać wejściowe kodowanie. >> I tę informację można wywnioskować z wartości zmiennych środowiskowych >> LC_*. Po Pythonie, który ma podobno świetną obsługę unicode, >> spodziewałem się, że takie pierdoły będzie miał "w standardzie". > Chyba nie rozumiem czego oczekujesz. Chciałbyś aby funkcja `len` > zwracała liczbę znaków stringa, a nie faktyczną ilość bajtów? Jeśli na początku oznajmiamy, że rozmawiamy w UTF8, to oczekiwać należy traktowania naszych słów jako UTF8. Instancja string jest dla mnie obiektem ciągu _znaków_, a nie _bajtów_. Wyjaśniłeś mi, że źle to zrozumiałem i słowem (w znaczeniu ciągu znaków) w Pythonie jest obiekt Unicode, jednakże albo ja go nie potrafię używać, albo jest on nieużywalny (vide mój test powyżej).
> To mi trochę przypomina wątek na comp.lang.python, gdzie koleś > koniecznie chciał znać liczbę bajtów obiektu unicode bez > użycia konkretnego kodowania. To akurat nie jest problemem, gdyż każdy znak spoza niskiego przedziału ASCII wystarczy policzyć podwójnie.
Pozdrawiam Beorn
-- Sygnatura w remoncie
William - 29-12-2006 00:25
> No właśnie. Spodziewałem się, że skoro w nagłówku skryptu zdefiniowałem > kodowanie jako Unicode, to Python wszystkie ciągi znaków będzie > traktował jako wielobajtowe z uwzględnieniem systemowego ustawienia locale.
Zadeklarowałeś w nagłówku tylko i wyłącznie system kodowania pliku ŹRÓDŁOWEGO programu. To o czym myślisz zrealizujesz przez podanie parametru -U przy URUCHOMIENIU interpretera (python -U plik.py)
> print len(unicode('Zażółć gęślą jaźń'))
Wystarczyłoby użyć: > print len( u'Zażółć gęślą jaźń' )
Skoro chcesz powołać do życia napis unicode używasz literału u'' albo przełącznika -U.
> traktowania naszych słów jako UTF8. Instancja string jest dla mnie > obiektem ciągu _znaków_, a nie _bajtów_. Wyjaśniłeś mi, że źle to
Można się spierać o to, czy dobrze jest że język wspiera zarówno napisy bajtowe jak i znakowe, czy też powinien odciąc się od tych pierwszych (tak jak jest to w javascripcie). Z powodu kompatybilności wstecz python na pewno będzie długo jeszcze posiadał oba typy. Zapewne tylko w którejś wersji (3.0 ?) literały nie poprzedzone żadnym określnikiem staną się domyslnie unicodowymi.
> To akurat nie jest problemem, gdyż każdy znak spoza niskiego przedziału > ASCII wystarczy policzyć podwójnie.
Nieprawda, znaki np. chińskie w utf-8 mogą mieć i 3 bajty
ramok - 29-12-2006 00:25
> print len(unicode('Zażółć gęślą jaźń')) > [beorn@rei ~]$ python -OO test.py > Traceback (most recent call last): > File "test.py", line 4, in ? > print len(unicode('Zażółć gęślą jaźń')) > UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 2: > ordinal not in range(128)
A co jeśli określisz KODOWANIE jako parametr? np: print len(unicode('Zażółć gęślą jaźń', 'iso-8859-2'))
Zadziała? ;P
beorn@alpha.pl - 29-12-2006 00:25
William writes: > Zadeklarowałeś w nagłówku tylko i wyłącznie system kodowania pliku > ŹRÓDŁOWEGO programu. To o czym myślisz zrealizujesz przez podanie > parametru -U przy URUCHOMIENIU interpretera (python -U plik.py) No właśnie to mnie boli.
>> print len(unicode('Zażółć gęślą jaźń')) > Wystarczyłoby użyć: > > print len( u'Zażółć gęślą jaźń' ) Nie mogę, gdyż ciąg znaków mam w zmiennej. Test był tylko testem.
> Skoro chcesz powołać do życia napis unicode używasz literału u'' albo > przełącznika -U. Przełącznik -U chce ode mnie BOMa.
>> To akurat nie jest problemem, gdyż każdy znak spoza niskiego przedziału >> ASCII wystarczy policzyć podwójnie. > Nieprawda, znaki np. chińskie w utf-8 mogą mieć i 3 bajty Prawda, ale to już jest chyba UTF16
Pozdrawiam Beorn
-- Sygnatura wciąż w remoncie
beorn@alpha.pl - 29-12-2006 00:25
ramok writes: >> print len(unicode('Zażółć gęślą jaźń')) >> [beorn@rei ~]$ python -OO test.py >> Traceback (most recent call last): >> File "test.py", line 4, in ? >> print len(unicode('Zażółć gęślą jaźń')) >> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 2: >> ordinal not in range(128) > > A co jeśli określisz KODOWANIE jako parametr? np: > print len(unicode('Zażółć gęślą jaźń', 'iso-8859-2')) > > Zadziała? ;P Ale tu chodzi o to, że nie wiadomo w jakim języku jest ciąg znaków. To, iż napisałem po polsku nie znaczy, że stringi są z polskimi zaroślami, lecz że nie mam mapy klawiatury np. z cyrylicą ;) Owszem, mogę sam zaimplementować mechanizm znajdowania kodowania, myślałem jednak, że interpreter się o takie rzeczy zatroszczy.
Pozdrawiam Beorn
-- Bez zmian
ramok - 29-12-2006 00:25
> Ale tu chodzi o to, że nie wiadomo w jakim języku jest ciąg znaków. No niestety to raczej trzeba wiedzieć... Inaczej każdy, nawet najkrótszy string musiałby 'nieść ze sobą' informację o swoim kodowaniu itp.
> Owszem, mogę sam zaimplementować mechanizm znajdowania kodowania, > myślałem jednak, że interpreter się o takie rzeczy zatroszczy. Jedyne co może Ci pomóc to sys.getdefaultencoding() i sys.stdout.encoding (u mnie, w konsoli pod windozą-> 1:'ascii', 2:'cp852'), ew. inne metody, w tym z modułu locale.
Pozdrawiam! /ramok
William - 29-12-2006 00:25
> Nie mogę, gdyż ciąg znaków mam w zmiennej. Test był tylko testem.
No to w ogóle nie rozumiem twojego problemu. Na logikę "zmienna" może pochodzić albo z przekształcenia literałów zapisanych w kodzie źródłowym (i na to pomoże -U i deklaracja kodowania pliku źródłowego - domyslnie utf-8), albo też pochodzić z systemu zewnętrznego (plik, protokół http, biblioteka). W tym drugim przypadku musisz rozpoznać system kodowania (z nagłówka http, nagłówka BOM pliku itp.). Nie ma cudu automagicznego rozpoznawania bo sysytemy plików, protokoły komunikacyjne są (i pewnie pozostaną) bajtowe a nie znakowe.
> >> Skoro chcesz powołać do życia napis unicode używasz literału u'' albo >> przełącznika -U. > Przełącznik -U chce ode mnie BOMa. >
U mnie nie chce :). Możesz przybliżyc problem ?
>>> To akurat nie jest problemem, gdyż każdy znak spoza niskiego >>> przedziału ASCII wystarczy policzyć podwójnie. >> Nieprawda, znaki np. chińskie w utf-8 mogą mieć i 3 bajty > Prawda, ale to już jest chyba UTF16
Nie. Znak unicode to znak i tyle. Czysto abstrakcyjny byt. UTF-7, UTF-8, UTF-16, UTF-32 itd. to tylko sposoby zapisania unicode w świecie bajtowym. UTF-8 może spokojne zapisać znaki azjatyckie na 3 bajtach.
beorn@alpha.pl - 29-12-2006 00:25
William writes:
>> Nie mogę, gdyż ciąg znaków mam w zmiennej. Test był tylko testem. > No to w ogóle nie rozumiem twojego problemu. Na logikę "zmienna" może > pochodzić albo z przekształcenia literałów zapisanych w kodzie źródłowym > (i na to pomoże -U i deklaracja kodowania pliku źródłowego - domyslnie > utf-8), albo też pochodzić z systemu zewnętrznego (plik, protokół http, > biblioteka). W tym drugim przypadku musisz rozpoznać system kodowania (z > nagłówka http, nagłówka BOM pliku itp.). Echhhh⌠MłodzieżâŚ Wszędzie tylko sieci komputerowe, łebfrejmłorki i GUI. A o wprowadzaniu danych w trybie tekstowym w terminalu juz nikt nie pamięta ;) Poza tym ja wiem w jakim kodowaniu będą wprowadzane dane i jest to niezmiennie UTF8. Ja nie wiem tylko na jakie miałbym to przekształcić żeby sprawdzić długość ciągu (zarówno poprzez combo zmienna.decode().encode() jak i rzeźbę w unicode()). Przyczyna jest prosta: nie wiem i nigdy wiedział nie będę jakiej narodowości będzie użytkownik, czy to będzie Polak, Rosjanin, Francuz, Duńczyk, czy może francuski rosjanin pochodzenia polskiego, który pisze po duńsku. Oni wszyscy będą mieli terminal UTF8.
> Nie ma cudu automagicznego > rozpoznawania bo sysytemy plików, protokoły komunikacyjne są (i pewnie > pozostaną) bajtowe a nie znakowe. Od tego jest właśnie locale, tylko problem w tym, iż nie często zdarza się umieszczanie deklaracji kodowania w zmiennych systemowych i trzeba robić mapowanie identyfikatorów kodowania na kody językowe locale (np. w przypadku pl_PL mamy UTF8 przekształcać na ISO8859-2). Jest to zdziebko upierdliwe, nie sądzisz? Oczywiście, możemy zrobić hardcode i poinformować uzytkowników, że wszystkie teksty jakie będą wprowadzać są traktowane jako polskie i w przypadku wystąpienia błędu prosimy pisać fonetycznym angielskim, albo kazać userowi się określic w jakim języku wciska te klawisze. Nadal jednak uważam, że interpreter powinien być na tyle lotny w kwestii obsługi UTF, że sam winien zająć się detekcją języka i na jej podstawie przeliczać długość znakową ciągu.
>>> Skoro chcesz powołać do życia napis unicode używasz literału u'' albo >>> przełącznika -U. >> Przełącznik -U chce ode mnie BOMa. > U mnie nie chce :). Możesz przybliżyc problem ? Proszę bardzo:
[beorn@rei ~]$ cat test.py #!/usr/bin/python # -*- coding: utf8 -*-
print len(unicode('Zażółć gęślą jaźń'))
[beorn@rei ~]$ python -U test.py 'import site' failed; use -v for traceback File "test.py", line 2 SyntaxError: encoding problem: with BOM
Wymaganie BOMa (jak i cała idea tego potworka) jest IMHO bzdurą.
>>>> To akurat nie jest problemem, gdyż każdy znak spoza niskiego >>>> przedziału ASCII wystarczy policzyć podwójnie. >>> Nieprawda, znaki np. chińskie w utf-8 mogą mieć i 3 bajty >> Prawda, ale to już jest chyba UTF16 > Nie. Znak unicode to znak i tyle. Czysto abstrakcyjny byt. UTF-7, UTF-8, > UTF-16, UTF-32 itd. to tylko sposoby zapisania unicode w świecie > bajtowym. UTF-8 może spokojne zapisać znaki azjatyckie na 3 bajtach. A, dobrze wiedzieć by później bzdur nie pleść.
Pozdrawiam Beorn
-- Sygnaturka⌠itd.
beorn@alpha.pl - 29-12-2006 00:25
ramok writes: >> Ale tu chodzi o to, że nie wiadomo w jakim języku jest ciąg znaków. > No niestety to raczej trzeba wiedzieć... Inaczej każdy, nawet najkrótszy > string musiałby 'nieść ze sobą' informację o swoim kodowaniu itp. Nie o kodowaniu, lecz o języku! Jest znaczna różnica. Kodowanie to zawsze UTF8.
>> Owszem, mogę sam zaimplementować mechanizm znajdowania kodowania, >> myślałem jednak, że interpreter się o takie rzeczy zatroszczy. > Jedyne co może Ci pomóc to sys.getdefaultencoding() i > sys.stdout.encoding (u mnie, w konsoli pod windozą-> 1:'ascii', > 2:'cp852'), ew. inne metody, w tym z modułu locale. Owszem, to wszystko się doskonale sprawdzi w przypadku kodowania, które odpowiada dokładnie jednemu językowi. UTF8 jest wielojęzyczny i informacja o tym, że znaki są w UTF8 nie ma dla mnie żadnej wartości, gdyż ja doskonale o tym wiem.
Pozdrawiam Beorn
-- âŚ
Rob Wolfe - 29-12-2006 00:25
beorn@alpha.pl writes:
> William writes: > >>> Nie mogę, gdyż ciąg znaków mam w zmiennej. Test był tylko testem. >> No to w ogóle nie rozumiem twojego problemu. Na logikę "zmienna" >> może pochodzić albo z przekształcenia literałów zapisanych w kodzie >> źródłowym (i na to pomoże -U i deklaracja kodowania pliku źródłowego >> - domyslnie utf-8), albo też pochodzić z systemu zewnętrznego (plik, >> protokół http, biblioteka). W tym drugim przypadku musisz rozpoznać >> system kodowania (z nagłówka http, nagłówka BOM pliku itp.). > Echhhh⌠MłodzieżâŚ Wszędzie tylko sieci komputerowe, łebfrejmłorki i > GUI. A o wprowadzaniu danych w trybie tekstowym w terminalu juz nikt > nie pamięta ;) > Poza tym ja wiem w jakim kodowaniu będą wprowadzane dane i jest to > niezmiennie UTF8. Ja nie wiem tylko na jakie miałbym to przekształcić > żeby sprawdzić długość ciągu (zarówno poprzez combo > zmienna.decode().encode() jak i rzeźbę w unicode()). Przyczyna jest > prosta: nie wiem i nigdy wiedział nie będę jakiej narodowości będzie > użytkownik, czy to będzie Polak, Rosjanin, Francuz, Duńczyk, czy może > francuski rosjanin pochodzenia polskiego, który pisze po duńsku. Oni > wszyscy będą mieli terminal UTF8.
A jakie znaczenie ma tutaj język??? Kodowanie to jest wszystko czego Ci potrzeba:
$ cat utf.py #!/usr/bin/env python #-*- coding: utf-8 -*-
import sys sys.stdout.write("Tekst: ") sys.stdout.flush() s = sys.stdin.readline() print type(s), repr(s), len(s), s s = s.decode("utf-8") print type(s), repr(s), len(s), s
$ python utf.py Tekst: zażółć <type 'str'> 'za\xc5\xbc\xc3\xb3\xc5\x82\xc4\x87\n' 11 zażółć
<type 'unicode'> u'za\u017c\xf3\u0142\u0107\n' 7 zażółć
Niezależnie od tego w jakim języku wklepiesz tekst, to powyższy program w ostatniej liniii zawsze pokaże Ci prawidłową liczbę znaków dopóki znaki te będą zakodowane w UTF8.
>> Nie ma cudu automagicznego rozpoznawania bo sysytemy plików, >> protokoły komunikacyjne są (i pewnie pozostaną) bajtowe a nie >> znakowe. > Od tego jest właśnie locale, tylko problem w tym, iż nie często zdarza > się umieszczanie deklaracji kodowania w zmiennych systemowych i trzeba > robić mapowanie identyfikatorów kodowania na kody językowe locale > (np. w przypadku pl_PL mamy UTF8 przekształcać na ISO8859-2). Jest to > zdziebko upierdliwe, nie sądzisz?
A po co mamy przekształcać na ISO-8859-2 skoro wszędzie w ustawieniach środowiskowych ma być UTF8. jak sam powiedziałeś?
> Oczywiście, możemy zrobić hardcode i poinformować uzytkowników, że > wszystkie teksty jakie będą wprowadzać są traktowane jako polskie i w > przypadku wystąpienia błędu prosimy pisać fonetycznym angielskim, albo
Jakiego błędu? Zamiana stringu zakodowanego w UTF8 na obiekt unicode nie powinna generować żadnych błędów.
> kazać userowi się określic w jakim języku wciska te klawisze. Nadal > jednak uważam, że interpreter powinien być na tyle lotny w kwestii > obsługi UTF, że sam winien zająć się detekcją języka i na jej > podstawie przeliczać długość znakową ciągu.
Poniższa funkcja zawsze zwróci prawidłową liczbę znaków w stringu, dopóki będzie on zakodowany w UTF8:
def char_count(s): return len(s.decode("utf-8"))
i język nie ma tu nic do rzeczy.
-- pozdrawiam Rob
William - 29-12-2006 00:25
1) Python nie potrzebuje microsoftowego nagłówka BOM, po to ma właśnie deklarację kodowania # -*- coding: utf8 -*- Jesteś pewnien, że twój edytor nie zapisał czegoś źle ? Podaj heksadecymalnie 3 pierwsze znaki twojego pilku .py.
2) Wreszcie okazało się z czym masz problem. Nie z pythonem ani z unicode tylko ze standardowym strumieniem stdin z biblioteki sys. Niestety jest on strumieniem bajtowym a nie znakowym. Tak samo jak każdy inny strumień I/O otwierany funkcja file albo open. Dopiero tez modułu codecs są strumieniami znakowymi unicode. Na szybko możesz posłużyć się banalną funkcją:
import sys
def stdinReadline(): """ Pobiera linijkę ze stdin ale jako unicode """
return unicode( sys.stdin.readline(), sys.stdin.encoding )
Ten strumień, choć bajtowy, ma atrybut "encoding" w któym zdradza swoje kodowanie (to będzie to twoje poszukiwane LOCALE shella w któym zostało to uruchomione).
A jako kontrargument do twojej myśli, że interpreter pownien sam korzystać z LOCALE do interpretacji stdin, to co ma zrobić jeśli ktoś przekieruje strumień ?
python plik.py < dane.txt
A dane są np. zakodowane w cp852 ??? Co ma wtedy zrobić biedny interpreter
Rob Wolfe - 29-12-2006 00:25
William <william@null.pl> writes:
> Nieprawda, znaki np. chińskie w utf-8 mogą mieć i 3 bajty
Ściślej mówiąc utf-8 koduje znaki na liczbie bajtów od 1-go do 4-ech.
-- pozdrawiam Rob
Piotr Dembiński - 29-12-2006 00:25
William <william@null.pl> writes:
> 1) Python nie potrzebuje microsoftowego nagłówka BOM
A to nie jest tak, że ten nagłówek jest też w normie?
Tomasz Torcz - 29-12-2006 00:25
Dzięki, William, za post o treści: > 1) Python nie potrzebuje microsoftowego nagłówka BOM, po to ma właśnie > deklarację kodowania # -*- coding: utf8 -*- Jesteś pewnien, że twój > edytor nie zapisał czegoś źle ? Podaj heksadecymalnie 3 pierwsze znaki > twojego pilku .py.
a) jakiego microsoftowego? b) przecież # -*- coding: utf8 -*- niesie informację całkowicie ortogonalną do BOM
-- Tomasz Torcz "God, root, what's the difference?" zdzichu@irc.-nie.spam-.pl "God is more forgiving."
Jarek Zgoda - 30-12-2006 01:04
Piotr Dembiński napisał(a):
>> 1) Python nie potrzebuje microsoftowego nagłówka BOM > > A to nie jest tak, że ten nagłówek jest też w normie?
Jest w normie. Norma dopuszcza i pozwala, norma nie wymaga.
-- Jarek Zgoda http://jpa.berlios.de/
Jarek Zgoda - 30-12-2006 01:04
Tomasz Torcz napisał(a):
>> 1) Python nie potrzebuje microsoftowego nagłówka BOM, po to ma właśnie >> deklarację kodowania # -*- coding: utf8 -*- Jesteś pewnien, że twój >> edytor nie zapisał czegoś źle ? Podaj heksadecymalnie 3 pierwsze znaki >> twojego pilku .py. > > a) jakiego microsoftowego? > b) przecież # -*- coding: utf8 -*- niesie informację całkowicie > ortogonalną do BOM
Mam nieodparte wrażenie, że BOM dotyczy czegoś innego, niż określenie sposobu kodowania reprezentacji unikodu, a lud myli wszystko ze wszystkim. O, tempora, o, mores!
-- Jarek Zgoda http://jpa.berlios.de/
William - 30-12-2006 01:04
Jarek Zgoda napisał(a): > Tomasz Torcz napisał(a): > >>> 1) Python nie potrzebuje microsoftowego nagłówka BOM, po to ma właśnie >>> deklarację kodowania # -*- coding: utf8 -*- Jesteś pewnien, że twój >>> edytor nie zapisał czegoś źle ? Podaj heksadecymalnie 3 pierwsze znaki >>> twojego pilku .py. >> a) jakiego microsoftowego? >> b) przecież # -*- coding: utf8 -*- niesie informację całkowicie >> ortogonalną do BOM > > Mam nieodparte wrażenie, że BOM dotyczy czegoś innego, niż określenie > sposobu kodowania reprezentacji unikodu, a lud myli wszystko ze > wszystkim. O, tempora, o, mores! >
BOM pozwala na rozróżnienie 5 postaci reprezentacji unikodu w pliku bajtowym:
UTF-16-LE UTF-16-BE UTF-32-LE UTF-32-BE UTF-8
Nagłówek pythonowy # -*- coding: pozwala na wskazanie w większym zbiorze , co jeszcze mam ci wytłumaczyć ?
Jarek Zgoda - 30-12-2006 01:04
William napisał(a):
>> Mam nieodparte wrażenie, że BOM dotyczy czegoś innego, niż określenie >> sposobu kodowania reprezentacji unikodu, a lud myli wszystko ze >> wszystkim. O, tempora, o, mores! > > BOM pozwala na rozróżnienie 5 postaci reprezentacji unikodu w pliku > bajtowym: > > UTF-16-LE > UTF-16-BE > UTF-32-LE > UTF-32-BE > UTF-8 > > Nagłówek pythonowy # -*- coding: pozwala na wskazanie w większym zbiorze > , co jeszcze mam ci wytłumaczyć ?
No patrz Pan, a mnie się zdawało, że BOM określa tylko, czy plik jest zakodowany zgodnie z LE albo BE.
Ale w takim razie, nie ma możliwości rozpoznania UTF-7. Ani UTF-64? I UTF-128?
-- Jarek Zgoda http://jpa.berlios.de/
William - 31-12-2006 00:05
> > No patrz Pan, a mnie się zdawało, że BOM określa tylko, czy plik jest > zakodowany zgodnie z LE albo BE.
Nie, jest to znak unicodowy U+FEFF ("pusty") zakodowany jak i cały plik w odpowiednim schemacie UTF-xx-yy. Został tak dobrany żeby dla każdego z wariantów UTF wyglądał inaczej.
> > Ale w takim razie, nie ma możliwości rozpoznania UTF-7. Ani UTF-64? I > UTF-128? >
Tu chyba się pospieszyłem, BOM pozwoli na identyfikację każdego wariantu kodowania Unicode za pomocą UTF.
Tomasz Torcz - 31-12-2006 00:05
Dzięki, William, za post o treści: >> >> No patrz Pan, a mnie się zdawało, że BOM określa tylko, czy plik jest >> zakodowany zgodnie z LE albo BE. > > Nie, jest to znak unicodowy U+FEFF ("pusty") zakodowany jak i cały plik > w odpowiednim schemacie UTF-xx-yy. Został tak dobrany żeby dla każdego z > wariantów UTF wyglądał inaczej.
Potrafisz rozwinąć skrót "BOM" ?
-- Tomasz Torcz "Funeral in the morning, IDE hacking zdzichu@irc.-nie.spam-.pl in the afternoon and evening." - Alan Cox
Piotr Dembiński - 31-12-2006 00:05
Tomasz Torcz <zdzichu@irc.-spamu.nie.chce-.pl> writes:
[...]
> Potrafisz rozwinąć skrót "BOM" ?
'Bateria Oponujących Mózgów' :>
William - 31-12-2006 00:05
Tomasz Torcz napisał(a): > Dzięki, William, za post o treści: >>> No patrz Pan, a mnie się zdawało, że BOM określa tylko, czy plik jest >>> zakodowany zgodnie z LE albo BE. >> Nie, jest to znak unicodowy U+FEFF ("pusty") zakodowany jak i cały plik >> w odpowiednim schemacie UTF-xx-yy. Został tak dobrany żeby dla każdego z >> wariantów UTF wyglądał inaczej. > > Potrafisz rozwinąć skrót "BOM" ? >
Nie jest to pierwszy przypadek gdy akronim nie odpowiada rzeczywistemu znaczeniu.
beorn@alpha.pl - 03-01-2007 00:24
William writes: > 1) Python nie potrzebuje microsoftowego nagłówka BOM, po to ma właśnie > deklarację kodowania # -*- coding: utf8 -*- Jesteś pewnien, że twój > edytor nie zapisał czegoś źle ? Podaj heksadecymalnie 3 pierwsze znaki > twojego pilku .py. Jestem absolutnie pewien, gdyż skrypt tworzony jest w Vimie, który mi nie dodaje BOMa.
> 2) Wreszcie okazało się z czym masz problem. Nie z pythonem ani z > unicode tylko ze standardowym strumieniem stdin z biblioteki sys. > Niestety jest on strumieniem bajtowym a nie znakowym. Tak samo jak każdy > inny strumień I/O otwierany funkcja file albo open. Dopiero tez modułu > codecs są strumieniami znakowymi unicode. Na szybko możesz posłużyć się > banalną funkcją: Ja wiem, że mogę sobie sam zaimplementować. Chodziło mi o rozwiązanie "out-of-the-box".
> A jako kontrargument do twojej myśli, że interpreter pownien sam > korzystać z LOCALE do interpretacji stdin, to co ma zrobić jeśli ktoś > przekieruje strumień ? Masz rację. Nie wziąłem pod uwagę innego zastosowania stdin.
Pozdrawiam Beorn
-- j.w.
beorn@alpha.pl - 03-01-2007 00:24
Rob Wolfe writes: >> zmienna.decode().encode() jak i rzeźbę w unicode()). Przyczyna jest >> prosta: nie wiem i nigdy wiedział nie będę jakiej narodowości będzie >> użytkownik, czy to będzie Polak, Rosjanin, Francuz, Duńczyk, czy może >> francuski rosjanin pochodzenia polskiego, który pisze po duńsku. Oni >> wszyscy będą mieli terminal UTF8. > A jakie znaczenie ma tutaj język??? A, bo chciałem odstawiać kombinacje alpejskie, gdy to:
> s = s.decode("utf-8")
Załatwia całą sprawę. Dziękuję wszystkim za pomoc i naprostowanie myśli :)
Pozdrawiam Beorn
-- Segmentation fault
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
=?iso-8859-2?q?[mysql]_Grupowanie_rekord=F3w_wg_dat?=
=?iso-8859-2?Q?A_mo=BFe_zna_kto=B6_z_Was_jak=B1=B6_przegl=B1d ark=EA_do_?==?iso-8859-2?Q?ikon=3F?=
Problem z zapytanie,
[oracle] Jak dostać sumę z rekordów "powyższych"?
sql - blad podczas kompilacji
Grafika
Unique index problem
=?ISO-8859-2?Q?R=F3znice_miedzy_MySQLem_a_Postgresem_?=
[PostgreSQL] =?ISO-8859-2?Q?Du=BFa?= baza danych
eskport www w photoshopie
zanotowane.pldoc.pisz.plpdf.pisz.pltejsza.htw.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|