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