Edit detail for Cestina2.x revision 2 of 1

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



Čeština v Python 2.x

py25.png

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:

  1. Na první řádce uvést pythonovskou definici kódování, tedy např.: # -- coding: utf-8 --
  2. V tom stejném kodování to uložit - například v PSPadu navolit menu Formát - UTF-8 a uložit
  3. 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()
  1. 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
>>>

Č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.