HAYOUNG'S MEMO
파이썬의 문자열 인코딩 본문
파이썬의 문자열 인코딩¶
문자와 인코딩¶
파이썬 뿐 아니라 모든 컴퓨터에서 문자는 2진 숫자의 열 즉, 바이트 열(byte sequence)로 바뀌어 저장된다. 이를 인코딩(encoding)이라고 하며 어떤 글자를 어떤 숫자로 바꿀지에 대한 규칙을 인코딩 방식이라고 한다.
가장 기본이 되는 인코딩 방식은 아스키(ASCII) 방식이다.
한글의 경우 과거에는 EUC-KR 방식이 많이 사용되기도 했으나 최근에는 CP949 방식이 더 많이 사용된다.
유니코드¶
인코딩 방식이 글자마다 혹은 회사마다 다르기 때문에 발생하는 문제를 해결하고자 유니코드라는 것이 만들어졌다. 유니코드에서는 다음과 같은 표준을 정했다.
- 유니코드 코드 포인트 (unicode code point)
- 유니코드 인코딩 (UTF-8, UTF-16, UTF-32, ...)
유니코드 코드 포인트(code point) 또는 코드 포지션(code position)은 최대 4바이트의 숫자로 전 세계 모든 글자를 대응시킨 것이다. 파이썬 내부에서 문자를 메모리에 저장할 때 주로 사용된다(파이썬 3.3부터는 PEP 393에 의해 바뀌었다).
유니코드 인코딩은 실제로 유니코드 문자를 바이트 열로 바꾸어 파일 등에 저장할 때 사용되는 방식으로 영문 알파벳에 대해 ASCII 인코딩 방식과 호환하며 크기, 정렬 등의 문제를 고려하여 설계되었다. 과거의 EUC-KR, CP949 등은 한글이라는 문자에 대해 저장할 값을 지정하는 방식이지만, 유니코드 인코딩 방식은 유니코드 코드 포인트에 대해 저장할 값을 지정하는 방식이므로 유니코드 코드 포인트를 가지는 모든 글자를 하나의 방식으로 저장할 수 있다. UTF-8은 현재 가장 많이 사용되는 유니코드 인코딩 방식의 하나이다.
파이썬의 문자열 자료형¶
파이썬 3에서는 기본 문자열의 자료형이 유니코드이며 자료형의 이름은 str
이다. 그리고 바이트열로 저장하기 위한 bytearray
자료형도 지원한다. 다음과 같은 명령으로 바이트 열로 상호 변환할 수 있다.
bytearray
명령어로 유니코드를 바이트열로 변환b
접두사를 이용한 바이트열 리터럴(literal) 생성
그리고 유니코드 포인트 방식으로 저장하기 위한 unicode
타입도 지원한다. str
타입과 unicode
타입간의 변환을 위해서는 다음과 같은 방법을 사용한다.
unicode
명령어로 유니코드 코드 포인트 반환u
접두사를 이용한 유니코드 리터럴(literal) 생성- -> 리터럴: 프로그래밍 언어에서 직접적으로 입력된 값을 나타내는 용어 . 예를들어서 우리가 프로그램 소스에 16이라고 입력하면 16은 정수 리터럴이되며, "Hello"라고 하면 문자열 리터럴이된다
유니코드로 한글을 저장해야 하는 이유¶
만약 한글 문자열을 단순히 화면에 출력하거나 파일로 내보내기만 하는 것인 목적이라면 굳이 유니코드를 이용할 필요는 없다. 그러나 한글 문자열을 분석해야 한다면 반드시 유니코드로 변환해야 한다. 왜냐하면 유니코드가 아닌 인코딩된 바이트 열은 한글의 글자 수를 세거나 글자 단위로 분리하는 것이 어렵기 때문이다.
예를 들어 "가"라는 글자가 있을 때, 이 글자가 유니코드이면 문자열의 원소 수는 1로 계산된다. 하지만 바이트 열이면 인코딩 방식에 따라 달라질 수 있다.
u = "가"
len(u)
b = bytearray("가", 'cp949')
len(b)
바이트열이면 글자를 한글자씩 분리할 수도 없다.
u1 = "ABC"
u2 = "가나다"
print(len(u1), len(u2))
print(u1[0], u1[1], u1[2])
print(u2[0], u2[1], u2[2])
b1 = bytearray("ABC", 'cp949')
b2 = bytearray("가나다", 'cp949')
print(len(b1), len(b2))
print(chr(b1[0]), chr(b1[1]), chr(b1[2]))
print(chr(b2[0]), chr(b2[1]), chr(b2[2]), chr(b2[3]))
인코딩과 디코딩¶
유니코드를 바이트 열로 변환할 때는 인코드 encode
메서드를, 바이트 열을 유니코드로 변환할 때는 디코드 decode
메서드를 사용한다. 그런데 인코딩할 때는 출력 장치(콘솔, 주피터 노트북)가 어떤 인코딩을 지원하는지를 미리 알고 있어야 한다. 만약 출력 장치가 지원하지 않는 방식으로 인코딩하면 화면에는 이상한 글자만 보이게 된다.
예를 들어 현재 필자가 이 코드를 실행하는 주피터 노트북에서는 utf-8 인코딩을 지원한다. 따라서 CP949로 인코딩한 바이트 열은 글자가 깨져서 보인다.
u = "가나다"
type(u)
b1 = u.encode("cp949")
type(b1)
b1
b2 = u.encode("euc-kr")
type(b2)
b2
b3 = u.encode("utf-8")
type(b3)
b3
디코딩할 때도 바이트열이 원래 인코딩된 방식으로 디코딩해야 제대로 된 문자열을 얻을 수 있다.
b1.decode("cp949")
b2.decode("euc-kr")
b3.decode("utf-8")
b1.decode("utf-8")
b3.decode("cp949")
인코딩 설정¶
콘솔 입력이나 파일은 유니코드 포인트로 동작하는 것이 아니라 인코딩된 바이트 열로 동작한다. 따라서 파이썬이 콘솔로 입력된 코드나 스크립트 코드를 읽을 때는 이 코드가 어떤 방식으로 인코딩되어 있는지 알고 있어야 한다. 콘솔 입력이면 환경 변수 PYTHONIOENCODING
으로 지정하고, 스크립트(파일)이면 첫 줄에 다음처럼 인코딩 설정 정보를 넣어 주면 된다.
#-*- coding: utf-8 -*-
'자연어처리' 카테고리의 다른 글
scikit-learn 패키지 (0) | 2019.01.29 |
---|---|
pandas 패키지의 dataframe 인덱싱(열/행/boolean 인덱싱), .iloc, .loc (0) | 2019.01.29 |
Label Encoding and One Hot Encoding (0) | 2019.01.29 |
파이썬 KoNLPy 패키지 사용 방법 (0) | 2019.01.23 |
형태소 분석기 성능 비고 (0) | 2019.01.23 |