Python에서 한글을 사용할때에 관련된 사항들.

유니코드와 문자열

유니코드(UniCode)는 전세계 언어의 통일된 문자체계이고, 문자열(String)은 각 사용자환경에서 이를 눈으로 볼 수 있도록 변환한 것이다. 사용자환경은 제각각이기때문에 (예를 들어, Windows XP는 cp949, UbuntuLinuxUTF8, 기타등등 CharacterSet) 유니코드문자를 제대로 보려면, 사용자환경에 맞게끔 문자열로 변환(인코딩)해야 한다.

UniCode <--> String

유니코드를 문자열로 변환하는 것을 인코딩이라고 하고, 문자열을 유니코드로 변환하는 것을 디코딩이라고 한다. 인코딩이란 어떤 규정된 형식으로 변환하는 것을 의미하며, 디코딩은 다시 원래의 정보를 보는 것을 의미한다. 어떤 유니코드를 UTF-8 문자열로 인코딩했다고 함은 UTF-8의 규정된 형식으로 정보를 변환했다는 의미이다.

괴도루팡과 설록홈즈가 등장하는 추리소설에 나오는 암호문을 상상하면 좋다. 다른사람이 못알아보게끔 특정정보를 어떤 형식에 맞도록 암호로 변환을 했으면, 이는 인코딩이고, 그것을 다시 누군가가 풀어냈다면, 디코딩을 한것이다. 유니코드의 세계에선 유니코드로 돌아가는 것이 디코딩이다.

Python에서는 유니코드와 문자열의 표현이 다음과 같다. (Windows XP에서 테스트)

   1 >>> a = '한글'  # 문자열
   2 >>> type(a)
   3 <type 'str'>
   4 >>> b = u'한글' # 유니코드
   5 >>> type(b)
   6 <type 'unicode'>
   7 >>>
   8 >>> c = a.decode('cp949')  # 문자열 --> 유니코드
   9 >>> type(c)
  10 <type 'unicode'>
  11 >>> b == c
  12 True
  13 >>> b.encode('cp949') == a # 유니코드 --> 문자열
  14 True
  15 >>>

위 예에서, a는 문자열이고, b,c는 유니코드이다. '한글' 이라고 눈으로 볼 수 있는 것 자체가 이미 인코딩된 문자열이라는 것을 의미하는 것이다. 인코딩을 했다면, 어떤 사용자환경으로(CharacterSet) 인코딩을 했느냐가 중요한데, 위 테스트는 Windows XP 기본 설정상황에서 했으므로, cp949로 인코딩되어 있는 것이다. 따라서, c변수에서 볼 수 있듯이 이를 다시 유니코드로 디코딩하려면, 원래 무엇으로 인코딩되어 있는가를 인수로 주어야 하는 것이다.

유니코드로의 디코딩방법은 다양하다.

  1. u"" : 문자열 따옴표 앞에 u를 붙인다. 이 경우, 현재사용되고 있는 charset, 혹은 소스코드의 인코딩으로 자동 디코딩된다.
  2. unicode(astr, charset)
  3. astr.decode(charset)

인코딩방법은 유니코드객체에 직접 encode 메쏘드를 charset 인수와 함께 사용하면 된다.

파이썬 기본 인코딩

sys.getdefaultencoding() 으로 확인할 수 있다. 설치시 기본 인코딩은 ASCII이다. python lib 디렉토리에 sitecustomize.py 를 다음처럼 만들면 이를 원하는 값으로 변경할 수 있다.

$ cat > /usr/lib/python2.5/sitecustomize.py << EOF
import sys
sys.setdefaultencoding('utf-8')
EOF

사용되는 곳은

  1. 유니코드 파일입력의 기본 인코딩

파이썬 소스코드 자체에 대한 기본 인코딩은 "iso-8859-1" 이었으나, Python2.5 부터 ASCII가 사용된다. http://python.kr/viewtopic.php?t=22395 참고.

소스코드 최상단 혹은 둘째줄에 다음을 적어줌으로써 변경할 수 있다.

# -*- coding:utf-8 -*-

파일 입출력

open(filename).read() 로 읽은 내용은 미지의 인코딩의 문자열이다. print 등의 명령으로 출력해봤을 때, 터미널환경의 인코딩과 일치하면 제대로 보여지지만, 그렇지 않으면 깨진 상태로 보여진다.

문자열을 그대로 파일에 쓰면 그대로 저장되지만, 유니코드를 직접 파일에 쓰면, 파이썬 기본인코딩으로 자동 인코딩되어 저장된다.

   1 # -*- coding:UTF-8 -*-
   2 f = open('h.txt','w')
   3 f.write(u'한글')
   4 f.close()
   5 a = open('h.txt').read()
   6 print a.decode('utf-8').encode('cp949')

위 코드는 sys.getdefaultencoding() 이 ascii 인 경우에는 u'한글' 의 ascii 로의 인코딩이 불가능하기 때문에 UnicodeEncodeError 예외가 발생한다. (coding:UTF-8 은 소스코드 자체의 인코딩이므로, 파일 f와는 관련이없다.) defaultencoding 을 UTF-8으로 바꾸면, 유니코드가 UTF-8으로 변환되어 저장된다.

한글이 깨진다는 것

다음의 환경이 다를 경우, 한글이 제대로 표시되지 않는다.

  1. 저장된 정보의 인코딩
  2. 디스플레이환경 (터미널, 에디터, 웹브라우저 등)

주요 모듈

  1. hangul.py by [Perky]

각종 팁

한글이 있는지 체크(UniCode로 변환후, 확인하는 방법사용) from http://bbs.python.or.kr/viewtopic.php?t=20797

   1 >>> def is_hangul(s): 
   2 ...     for c in unicode(s): 
   3 ...             if u'\uac00' <= c <= u'\ud7a3': 
   4 ...                     return True 
   5 ...     return False 
   6 ... 
   7 >>> is_hangul('abc가나다') 
   8 True 
   9 >>> is_hangul('abc') 
  10 False 
  11 >>> 

주어(명사)의 마지막 음절이 종성을 갖느냐 아니냐에 따라 조사가 달라진다. (예, 철수가, 형용이가). 이를 체크하는 코드. hangul.py 필요

   1 >>> import hangul
   2 >>> haveJongsung=lambda u: hangul.split(u[-1])[-1] and True or False
   3 >>> haveJongsung(unicode('자음','utf-8'))
   4 True
   5 >>> haveJongsung(unicode('','utf-8'))
   6 False

참고

PythonAndHangul (last edited 2014-12-04 12:12:17 by 166)

web biohackers.net