2 | ||
Editor: geon
Time: 2011/10/10 21:00:26 GMT+2 |
||
Note: pridavani znacek 2x-3x |
changed: - Čeština v Python 2.x ============================ .. image:: py25.png :align: right .. contents:: Obsah Kódování vlastního textu programu --------------------------------- Pro správné fungování češtiny v samotném programu je třeba dodržet 3 hlavní zásady: #. Na první řádce uvést pythonovskou definici kódování, tedy např.: # -*- coding: utf-8 -*- #. V tom stejném kodování to uložit - například v !PSPadu navolit menu Formát - UTF-8 a uložit #. Před všechny řetězce dát znak 'u' (jako Unicode), tedy např. :: # -*- coding: utf-8 -*- veta=u"Žluťoučký kůň pěl ďábelské ódy." print veta Poznámka: pokud použijete kodování utf-8 není potřeba vkládat před řetězce znak "u". U všech ostatních to je nutné. Kódování vstupů --------------------------------- Máte-li ve svém programu žádost na vstup od uživatele (klasicky input() či raw_input()), je hodnota vrácena v kódování, které získáte příkazem:: import sys print sys.stdin.encoding Standardně pod Windows se jedná o cp852, pod Linuxem ... Používáte-li jakékoliv GUI a žádáte uživatele o vstup, bude kódování s největší pravděpodobností utf-8. Jinými slovy u GUI aplikací neplatí sys.stdin.encoding. Kódování názvů souborů a adresářů --------------------------------- Pracujete-li ve svém programy s názvy souborů a složek, je nejlépe žádat systém o seznamy předáváním parametru cesty s "u" (unicode). Např. u"." - aktuální adresář v unicode. Bude vrácen seznam také v kodování unicode. Pokud nepředáte parametr s "u", bude vráceno v kodování sys.getfilesystemencoding() :: print os.listdir(u".") # seznam v unicode print os.listdir(".") # seznam v kodování souborového systému print sys.getfilesystemencoding() # kodování souborového systému Kódování obsahu souborů --------------------------------- Platí, že se nedá "přesně určit", "automaticky detekovat", v jakém kódování, je ten který text. Dá se to "odhadnout" - umí to např. unixový program file a enca. Tyto programy se dají najít i pro Windows, ale je problém je pod Windows rozchodit (kompilace). Nejjistější zůstává určovat kódování přesně a ručně - tedy třeba u textových editorů nechat uživatele, ať si zvolí sám, nebo u přijímaných dat si nechávat posílat i kódování. Výjimku tvoří kódování textu v utf-8, kde platí .... doplnit ..... Kódování defaultencoding --------------------------------- **sys.getdefaultencoding()**:: import sys print sys.getdefaultencoding() **sys.setdefaultencoding()**:: Pro správné kodování - například pro UTF vstup z SQL - stačí jediné: buď ve svém programu přidat řádky:: import sys sys.setdefaultencoding('utf-8') nebo v adresáři *site-packages* vytvořit soubor *sitecustomize.py* se stejným obsahem. Touto úpravou se odstraní oblíbená hláška: *'ascii' codec can't encode characters*. Pozn.: místo utf-8 může být i jiné, např. iso-8859-2. Praktická zkouška --------------------------------- :: # -*- coding: iso-8859-2 -*- # tento soubor by měl být uložen v kodovani iso-8859-2 # je to důležité, aby byla shoda mezi uloženým a deklarovaným kodovanim # 'textUni' je uložen v iso-8859-2 (protože je v něm celý soubor) # a je rovnou na Unicode převeden (u na začátku řetězce), # takže nebude problém ho tisknout - nejpoužívanější způsob textUni=u'Žluťoučký kůň pěl ďábelské ódy' print "Spravne:", textUni #------------------------------------------------------- # 'text' je uložen také v iso-8859-2 (ale bez převodu na Unicode) text='Žluťoučký kůň pěl ďábelské ódy' # takže když ho chceme vytisknout správně vždy a všude # musíme ho převést na Unicode takto: print "Spravne:", unicode(text,'iso-8859-2') # nebo takto print "Spravne:", text.decode('iso-8859-2') # pokud bychom omylem nepoužili žádnou konverzi, dostaneme hatmatilku print "Spatne:", text # pokud pouzijeme špatné kodovaní, dostaneme chybu # print "Spatne, dokonce s chybou:", unicode(text,'cp1250') # převod tam a hned zpět, takže stejné jako "print text" print "Tam a hned zpet, spatne:", unicode(text,"iso-8859-2").encode("iso-8859-2") Malá písmena na velká (po česku) --------------------------------- :: # -*- coding: cp1250 -*- import locale print u"řčššě".upper() locale.setlocale(locale.LC_ALL, "czech") print u"řčššě".upper() Řazení (po česku) --------------------------------- :: #!/usr/bin/python # -*- coding: utf-8 -*- import locale seznam=["žízeň", "zábava", "údy", "uzel", "chlap", "čumil", "důkaz", "civil", "řetěz", "rozum", "ábel", "atom", "óda", "ovar"] locale.setlocale(locale.LC_ALL,'czech') seznam=[x.decode("utf-8") for x in seznam] seznam.sort(lambda a,b: locale.strcoll(a, b)) for slovo in seznam: print slovo Převod mezi různými znakovými sadami --------------------------------- 1) Převod je možné dělat přes unicode kódování, tedy nejdříve převést vstupní řetězec na unicode (při znalosti použitého kodování) a pak z unicode na požadované. :: vstup = file("vstup.txt", "r") vystup = file("vystup.txt", "w") for radek in vstup: radek = radek.decode('iso-8859-2').encode('cp1250') print radek, vystup.write(radek) vstup.close() vystup.close() 2) Využitím modulu codecs. :: import codecs vstup = codecs.open("vstup.txt", "r", "iso-8859-2") vystup = codecs.open("vystup.txt","w","cp1250") for radek in vstup: print radek, vystup.write(radek) vstup.close() vystup.close() Odstranění diakritiky --------------------------------- Obyčejné řetězce:: # -*- coding: cp1250 -*- import string line="Žluťoučký kůň pěl ďábelské ódy" table=string.maketrans("áčďéěíňóřšťúůüýžÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ","acdeeinorstuuuyzACDEEINORSTUUYZ") print line.translate(table) Unicode řetězce:: # -*- coding: utf-8 -*- import unicodedata line="Žluťoučký kůň pěl" line = unicode(line, 'utf-8') line = unicodedata.normalize('NFKD', line) output = '' for c in line: if not unicodedata.combining(c): output += c print output Seznamy a n-tice --------------------------------- Seznamy a n-tice neumí samy o sobě tisknout správně češtinu u svých prvků. Je třeba procházet prvek jeden po druhým a tisknout každý zvlášť:: >>> s=["žízeň", "zábava","údy", "čumil", "důkaz"] >>> print s ['\xa7\xa1ze\xe5', 'z\xa0bava', '\xa3dy', '\x9fumil', 'd\x85kaz'] >>> for prvek in s: ... print prvek, ... žízeň zábava údy čumil důkaz >>> Čtení souboru utf-8 s příznakem BOM ---------------------------------------- `Příznak BOM </ZpracovaniTextovehoSouboru#bom>`_ Čeština v input() i raw_input() ---------------------------------- Bohužel, použití češtiny v argumentu input() díky bugu ... není možné:: >>> vstup=raw_input(u"Zadej jméno") Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 8: ordinal not in range(128) Řešení je možné použitím příkazu print:: print u"Zadej jméno", vstup = raw_input() Ukládání unicode text do souboru --------------------------------- ...nelze. Je třeba před uložením text převést na nějaké normálnější kódování: utf8, cp1250, ....:: # -*- coding: utf-8 -*- text=u"Žluťoučký kůň pěl ďábelské ódy." f=open("Kun.txt","w") f.write(text) # způsobí error f.write(text.encode("utf8")) # ok f.close() Čeština v komentářích ------------------------- Objeví-li se kdekoliv v programu, třeba i v komentáři, český znak, je nutné uvést definici kódování, jinak získáte SyntaxError. Záložky, Oblíbené ----------------- Unicode HOWTO: http://www.amk.ca/python/howto/unicode
Obsah
Pro správné fungování češtiny v samotném programu je třeba dodržet 3 hlavní zásady:
# -*- coding: utf-8 -*- veta=u"Žluťoučký kůň pěl ďábelské ódy." print veta
Poznámka: pokud použijete kodování utf-8 není potřeba vkládat před řetězce znak "u". U všech ostatních to je nutné.
Máte-li ve svém programu žádost na vstup od uživatele (klasicky input() či raw_input()), je hodnota vrácena v kódování, které získáte příkazem:
import sys print sys.stdin.encoding
Standardně pod Windows se jedná o cp852, pod Linuxem ...
Používáte-li jakékoliv GUI a žádáte uživatele o vstup, bude kódování s největší pravděpodobností utf-8. Jinými slovy u GUI aplikací neplatí sys.stdin.encoding.
Pracujete-li ve svém programy s názvy souborů a složek, je nejlépe žádat systém o seznamy předáváním parametru cesty s "u" (unicode). Např. u"." - aktuální adresář v unicode. Bude vrácen seznam také v kodování unicode. Pokud nepředáte parametr s "u", bude vráceno v kodování sys.getfilesystemencoding()
print os.listdir(u".") # seznam v unicode print os.listdir(".") # seznam v kodování souborového systému print sys.getfilesystemencoding() # kodování souborového systému
Platí, že se nedá "přesně určit", "automaticky detekovat", v jakém kódování, je ten který text. Dá se to "odhadnout" - umí to např. unixový program file a enca. Tyto programy se dají najít i pro Windows, ale je problém je pod Windows rozchodit (kompilace).
Nejjistější zůstává určovat kódování přesně a ručně - tedy třeba u textových editorů nechat uživatele, ať si zvolí sám, nebo u přijímaných dat si nechávat posílat i kódování.
Výjimku tvoří kódování textu v utf-8, kde platí .... doplnit .....
sys.getdefaultencoding():
import sys print sys.getdefaultencoding()
sys.setdefaultencoding():
Pro správné kodování - například pro UTF vstup z SQL - stačí jediné: buď ve svém programu přidat řádky:
import sys sys.setdefaultencoding('utf-8')
nebo v adresáři site-packages vytvořit soubor sitecustomize.py se stejným obsahem. Touto úpravou se odstraní oblíbená hláška: 'ascii' codec can't encode characters. Pozn.: místo utf-8 může být i jiné, např. iso-8859-2.
# -*- coding: iso-8859-2 -*- # tento soubor by měl být uložen v kodovani iso-8859-2 # je to důležité, aby byla shoda mezi uloženým a deklarovaným kodovanim # 'textUni' je uložen v iso-8859-2 (protože je v něm celý soubor) # a je rovnou na Unicode převeden (u na začátku řetězce), # takže nebude problém ho tisknout - nejpoužívanější způsob textUni=u'Žluťoučký kůň pěl ďábelské ódy' print "Spravne:", textUni #------------------------------------------------------- # 'text' je uložen také v iso-8859-2 (ale bez převodu na Unicode) text='Žluťoučký kůň pěl ďábelské ódy' # takže když ho chceme vytisknout správně vždy a všude # musíme ho převést na Unicode takto: print "Spravne:", unicode(text,'iso-8859-2') # nebo takto print "Spravne:", text.decode('iso-8859-2') # pokud bychom omylem nepoužili žádnou konverzi, dostaneme hatmatilku print "Spatne:", text # pokud pouzijeme špatné kodovaní, dostaneme chybu # print "Spatne, dokonce s chybou:", unicode(text,'cp1250') # převod tam a hned zpět, takže stejné jako "print text" print "Tam a hned zpet, spatne:", unicode(text,"iso-8859-2").encode("iso-8859-2")
# -*- coding: cp1250 -*- import locale print u"řčššě".upper() locale.setlocale(locale.LC_ALL, "czech") print u"řčššě".upper()
#!/usr/bin/python # -*- coding: utf-8 -*- import locale seznam=["žízeň", "zábava", "údy", "uzel", "chlap", "čumil", "důkaz", "civil", "řetěz", "rozum", "ábel", "atom", "óda", "ovar"] locale.setlocale(locale.LC_ALL,'czech') seznam=[x.decode("utf-8") for x in seznam] seznam.sort(lambda a,b: locale.strcoll(a, b)) for slovo in seznam: print slovo
vstup = file("vstup.txt", "r") vystup = file("vystup.txt", "w") for radek in vstup: radek = radek.decode('iso-8859-2').encode('cp1250') print radek, vystup.write(radek) vstup.close() vystup.close()
import codecs vstup = codecs.open("vstup.txt", "r", "iso-8859-2") vystup = codecs.open("vystup.txt","w","cp1250") for radek in vstup: print radek, vystup.write(radek) vstup.close() vystup.close()
Obyčejné řetězce:
# -*- coding: cp1250 -*- import string line="Žluťoučký kůň pěl ďábelské ódy" table=string.maketrans("áčďéěíňóřšťúůüýžÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ","acdeeinorstuuuyzACDEEINORSTUUYZ") print line.translate(table)
Unicode řetězce:
# -*- coding: utf-8 -*- import unicodedata line="Žluťoučký kůň pěl" line = unicode(line, 'utf-8') line = unicodedata.normalize('NFKD', line) output = '' for c in line: if not unicodedata.combining(c): output += c print output
Seznamy a n-tice neumí samy o sobě tisknout správně češtinu u svých prvků. Je třeba procházet prvek jeden po druhým a tisknout každý zvlášť:
>>> s=["žízeň", "zábava","údy", "čumil", "důkaz"] >>> print s ['\xa7\xa1ze\xe5', 'z\xa0bava', '\xa3dy', '\x9fumil', 'd\x85kaz'] >>> for prvek in s: ... print prvek, ... žízeň zábava údy čumil důkaz >>>
Bohužel, použití češtiny v argumentu input() díky bugu ... není možné:
>>> vstup=raw_input(u"Zadej jméno") Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 8: ordinal not in range(128)
Řešení je možné použitím příkazu print:
print u"Zadej jméno", vstup = raw_input()
...nelze. Je třeba před uložením text převést na nějaké normálnější kódování: utf8, cp1250, ....:
# -*- coding: utf-8 -*- text=u"Žluťoučký kůň pěl ďábelské ódy." f=open("Kun.txt","w") f.write(text) # způsobí error f.write(text.encode("utf8")) # ok f.close()
Objeví-li se kdekoliv v programu, třeba i v komentáři, český znak, je nutné uvést definici kódování, jinak získáte SyntaxError.