위의 코드는 print unicode(line) 으로 출력시 오류가 발생 함.
print unicode(line, 'cp949')
한글 처리를 위해 위의 코드처럼 cp949를 유니코드로 변환 해주면 한글이 잘 출력이 된다.
Simple 테스트 코드
|
읽어볼만한 글!
이글은 파이썬 초보의 글입니다. 그리고 새로 들어오는 파이썬 초보를 위한 글입니다. johnsonj의 개인적인 생각에 불과하므로 전적으로 신뢰하시질 마시길 부탁드립니다. |
윈도우에서의 파이썬 유니코드 한글 처리 문제
이 글은 한글 문제로 고민을 하는 파이썬 초보자를 위한 글입니다. 복잡한 이론은 설명할 능력도 되지 않습니다. 오직 표면상으로 드러난 문제에서 부터 역으로 추론해 보고 있으며 그리고 전부 가정과 추론으로 가득차 있는 문서입니다. 이 글의 목적은 유니코드 한글 처리 전반에 대한 이해의 체계를 세우는데 있습니다. 물론 이론의 체계는 미완성입니다. 그럼에도 이글이 발표되는 이유는 한글코드 처리에 관한 한개의 지침서도 없는 상황에서 파이썬 초보자들이 머리를 맞대고 스스로 해결방안을 찾는 기폭제가 되기를 바라는 마음으로 글을 씁니다. 이글을 읽는 분이 반드시 명심해야할 사항은 다음과 같습니다. 우선 실행환경은 윈도우 98이고 파이썬 버전 2.1.1을 기준으로 하여 설명하겠습니다. 다른 운영환경은 테스트하지 못하였습니다. 자신의 실행환경을, 특히 코드에 대해 주의를 기울이지 않으면 이해할 수 없는 현상들에 계속해서 마주칠 것입니다.
윈도우에서 유니코드 한글 처리문제 혼란의 근원
파이썬이 유니코드를 지원한다고 하는데 실제로 유니코드를 이용하는데에는 많은 어려움이 있습니다. 그 문제를 파이썬에 돌리고 언제 해결되겠지하고 기다리고 있었습니다. 마냥 기다릴 수는 없어서 있는데로나 이용해보자 하고 열심히 테스트해 본 결과 한글이 문제를 일으키는 원인은 파이썬의 문제가 아니라 우리가 파이썬의 유니코드 입출력 체계를 이해하지 못해서 오는 오해의 결과가 아닌가 생각하게 되었습니다. 지금까지는 한글 코덱 설치와 idle 패치로 한글 문제를 그럭저럭 처리하고 있었습니다. 그러나 구이를 붙여 볼때 당하는 무지막지한 한글 문제는 도저히 이해 할 수 없는 문제였습니다.
문제의 핵심은 코드전환(encoding)!!!.
본인도 그렇게 생각했고 여러 한글 처리 문서를 종합해 볼때 코드전환을 euc-kr로 하라고 권장되고 있습니다. 문제는 그렇게 해도 한글 문제는 곳곳에서 튀어 나오는 것이었읍니다. 어차피 망가질 바에는 처음부터 해보자. 패치고 뭐고 전혀 없이 처음부터 시작하였습니다.
한글문제 혼란의 근원은 유니코드 한글 입출력 처리 시스템을 이해하지 못하는 데서 오는 수 많은 희망사항 때문입니다. 정확히 이야기 하면 입출력 체계에 대한 이해 없이 너무나 다양한 요구를 하고 있고 또 파이썬의 유연성 때문에 꼼수를 써서 그것이 가능하다는데 있습니다. 비록 그것이 가능하다 할지라도 그렇게 해서는 안되는 것이라고 생각합니다. 정확하게 무엇을 요구해야 하는지 그리고 그것을 파이썬에 맞추어 어떻게 이용할지 알아보고자 합니다. 이것은 가능성의 문제가 아닙니다. 최대한 편리한 환경을 갖추고자 하는데 목적이 있습니다.
- 1. 코드전환을 코드변환으로 혼동 - 코드 전환으로도 코드변환이 되기는 됩니다. 단 1 대 1 변환만이 옳은 사용방법입니다. mbcs에서 utf로 utf에서 uncode_escape등으로 세 개 이상의 코드 변환은 혼란만 야기할 뿐입니다. 이렇게 다양하게 변환하려면 차라리 변환라이브러리를 만들어서 import해서 쓰는 편이 훨씬 좋을 것입니다. 그런 라이브러리 사용하지 않고서도 코덱으로 별 문제 없이 변환하는 사람은 전문가입니다. 지금의 문제는 초보가 그런 용도로 사용하면서 발생하는 문제를 다루고자 하는 것입니다. encode()와 unicode() 선택사항이 왜 하나인지 생각해 보시길 바랍니다. 그리고 encode의 반대 개념은 decode인데 코드 변환할 때 이 메쏘드 사용하는 예를 보셨습니까?
- 2. 기본코드와 코드전환(encoding)의 개념에 대한 혼란 - 실제 기본 코드와 코드 사이의 전환에 사용되는 encoding이 이름이 같아서 상당한 혼란을 주고 있습니다. 기본코드와 기본코드전환은 이름은 같지만 전혀 다른 것입니다.
- 3. 기본코드전환을 고려하지 않은 파일 입력 - 미처 생각지 못한것이 콘솔에서 사용하던 mbcs(euc-kr)을 망각하고 다른 코드의 파일을 받아들여 처리하면 예상대로 처리되지 않습니다. marhal, shelve등등의 라이브러리는 utf-8이 입력되리라고 기대합니다. 앞으로도 많은 라이브러리들이 utf-8을 가정할 것이라고 합니다. 그런데 콘솔에서 설정했던 euc-kr을 고려하지 않으면 예상치 못한 결과에 봉착합니다.
한글 처리 연구의 발단
지금은 유니코드로 가는 과도기입니다. 이 과도기는 상당기간 지속될 것 같으므로 유니코드의 천하통일을 기다리기에는 너무 지루합니다. 어떻게 하든 한글 처리 메카니즘을 지금이라도 알아야 한다는 생각이 들었습니다.
아래는 제가 한글코드 문제를 생각하게된 계기인데 다른 사람들도 마찬가지가 아닐까요. 어쨋든 저만의 희망사항이라고 합시다. 구이에 출력하기 위해 이렇게 일일이 다음과 같은 함수 혹은 메쏘드를 사용하는 것이 과연 온당한가였습니다. 그리고 과도기에 처한 파이썬 유니코드의 처리방식은 그래서 한글을 사용하는 저에게 골치거리가 아닐 수 없습니다.
- 1. len()을 사용하기 위해 unicode()를 사용하는 것이 귀찮다.
- 2. 문자열마다 .encode() unicode()를 붙여서 출력하는게 부담스럽다
첫 번째, 출력을 위해서 encode와 unicode를 사용하는 것은 쓸데 없는 낭비라는 결론에 도달하였습니다. 저런 함수를 쓰지 않으면 출력이 안되는 줄 알았습니다. 그러나 그 이유가 기본코드전환이 euc-kr에 있다는 것입니다. 다른 코드를 다룰 때는 그냥 유니코드 지원편집기를 이용해서 편집하고 자신의 터미날에 맞는 코드로 저장해서 실행하는 것이 가장 편한 방법입니다.
두 번째, 지금의 프로그래밍 환경으로는 unicode()는 어쩔 수 없이 쓸 수 밖에 없습니다. 코드전환을 unicode로 설정하고 -U로 실행만 된다면 unicode()를 쓰지 않아도 되겠지만, 설사 그렇게 성공했다고 하더라도 나머지 구이들이 utf-8코드를 쓰는한 또 변환하지 않을 수 없습니다. 다시 말하면 유니코드로 넘어가는 과도기가 계속되는 한 어쩔 수 없이 unicode()를 써야 한다는 것입니다. 즉 1 번문제는 도전할 만한 이점이 별로 없습니다. 성공해도 남는게 없는 장사라는 것입니다. 적어도 지금의 환경으로서는 그렇다는 것입니다.
참고한 문서
파이썬 홈의 i18n동아리에 있는 세 건의 유니코드 관련 문서입니다.
파이썬 문서고에 있는 번역 문서를 참조 하였습니다:
- 파이썬 유니코드 제안서 - Mark Andre Lemburg : 파이썬 내부 코드 처리에 대한 확실한 설명이 있습니다
- 파이썬을 국제화하기 - Martin von L?is : 국제화에 대해 전반적으로 설명해 놓고 있습니다.
- 파이썬 유니코드 지침서 - Mark Andre Lemburg : 코드에 대한 이해를 돕기 위해 실제 사용예를 보여줍니다.
실행환경
다시 한번 환경을 확실하게 해 둡니다. 유니코드의 한글처리는 환경에 너무나 밀접하게 연관되어 있습니다.
- 한글 윈도우 98
- 파이썬 2.1.1 - 패치하지 않은 것, 한글코덱 설치 않은 것
가장 확실한 한글 해결책encoding은 마음대로 바꾸어서 설정할 수 있습니다. 이 사실은 오직 명령어 라인 인터프리터에만 해당합니다. 호환성은 전혀 상관없습니다. 그저 자신의 터미날에 맞게 사용하면 됩니다. encoding은 사용할 터미날(창, 파일)의 코드에 맞추어야 하는 고정된 값이라는 것입니다. 그러나 프로그래밍 파일을 만드시려면 utf-8이 표준입니다. 기본코드도 이것으로, 기본코드전환도 이것으로 설정해야 합니다. utf-8은 대세입니다. 기본코드전환을 개인의 기호에 맞게 마음대로 바꾸어서 사용하시는 것은 혼란의 구렁텅이에 빠지게 됩니다. 정확히 이야기하면 작동하지도 않습니다. 기본코드전환을 터미날의 환경에 맞게 각각 설정해주어야 하는데 이렇게 해야 하는 이유는 나중에 설명하고 성질급한 사람, 또는 이론까지는 필요없는 사람을 위하여 위 세 건의 문서를 참조한 결과로 나온 (제가 판단하기에) 가장 확실한 해결책을 먼저 말씀드립니다. 코드전환을 아래와 같이 맞추어 두어야 합니다. 다른 코드전환으로는 엄청난 불편을 감수해야 원하는 결과를 얻을 수 있습니다.
왜 IDLE에서 출력은 되는데 입력이 되지 않는가?시키는데로 encoding="utf"로 설정하였을지라도 한글은 입력이 안됩니다. 파이썬 메가 위젯을 받아 보시면 입력데모가 있는데 여기에서도 입력은 되지 않습니다. 원인이 무엇일까? 아무래도 tkinter와 한글이 맞지 않는가 보다라고 포기하고 있었는데 일본 파이썬 사용자 모임에서 해결책을 찾았습니다. 이것이 가능하게 됨으로써 한글 입출력 처리의 이론을 그나마 구성해 볼 수 있었습니다. 기본처리 코드 mbcs (1) utf-8 (2) ucs-2 분류 윈도우 - (Tkinter - 파이썬) IDLE 이 유 : 파이썬은 tcl디렉토리를 tkinter 모듈이 있는 디렉토리로 제대로 인식하고 있습니다. 그러나 tcl은 자신의 디렉토리를 fixtk.py의 버그 때문에 자신의 디렉토리를 인식하지 못하기 때문입니다. 입력을 가만히 추론해 보면 tkinter는 윈도우의 코드인 mbcs를 자신의 코드인 "utf-8"로 바꾸어야 하는데 변환메카니즘을 lib/tk8.3/encoding에서 찾기 때문이라고 생각됩니다(1). tcl이 변환한 "utf-8"은 새로운 입력이 되는데 lib/encoding에서 변환하여 비로서 파이썬에 건네어져 입력(ucs-2)될 수 있다는 것입니다(2). 이렇게 처리된 utf-8코드는 다시 출력을 위해 tkinter로 가고 여기에서 다시 mbcs로 변환되는 것이 아닌가 생각합니다. 해결책 :
부수적 효과: 입력 출력 풍선도움말에도 한글이 출력됩니다. Tkinter 프로그래밍하시는 분은 파이썬 메가 위젯을 사용하시면 아주 편리하리라 생각됩니다. 주운 정보: IDLE에서 한글 폰트 모양을 바꾸어 보려면 : IDLE 디렉토리에 있는 config-win.txt를 열어서 원하는 폰트로 바꿀 수 있습니다. 한글 폰트 이름은 반드시 utf-8로 저장해야 합니다. IDLE은 utf-8편집기를 가지고 있습니다. 구이 문제 (pygtk, pyqt, tkinter, wxpython, Fxpy)구이 프로그램은 에디터로 작성되는 것이 보통입니다. 실제로 구이에 출력되는 문자열은 편집기에 사용한 코드 그대로 보여집니다. 다시 말해서 코드전환과는 전혀 상관이 없습니다. 단순히 출력되는 문자열만을 보고 싶다면 코드전환은 아무거나 설정해도 됩니다. 다시 말해서 편집기의 코드와 구이의 코드가 일치만 한다면 지저분하게 .encode()를 사용할 필요가 전혀 없습니다. 그런데 코드전환은 절대로 편집기에서 사용한 코드와 똑같이 일치시켜야 합니다. 이유는 문자열 처리에서 문제가 발생하기 때문입니다. 즉 unicode()로 유니코드 처리를 하고 len()을 사용하면 개수가 예상하지 못한 결과가 나옵니다. 다시 말해서 코드전환을 설정하는 문제는 입출력과 상관이 없고 문자열 처리를 위해 unicode()를 사용할 때 발생하는 문제와 연관이 있다는 것입니다. 다음과 같은 구이 프로그램은 거의 에디터로 작성하실 것이고 기본 코드전환에 맞추어 저장하여야 한다는 것입니다. 각 구이의 기본 코드는 나름대로 고정되어 정해져 있다고 판단되는바, 1. wxpython, Fxpy : 필수 encoding="mbcs" 2. pygtk, pyqt, tkinter : 필수 encoding="utf-8" 즉 편집기코드-구이코드-코드전환이 혼연 일체가 되어야 한다는 것입니다. |
유니코드 입출력 체계의 이해
역시 결론부터 이야기한다면, 파이썬 코어는 절대로 빠질수 없는 중심이고 그 코드는 ucs-2입니다. 즉어도 변환의 소스와 타켓중 하나는 반드시 ucs-2이라는 것입니다. encode,decode,unicode 는 파이썬의 ucs-2를 반드시 가정하고 있습니다. 그리고 나머지 하나는 인간이 보고 있는 화면의 코드입니다. encoding은 나머지 하나, 즉 인간의 화면에 있는 코드 형태를 담고 있는 변수가 됩니다. 마음대로 화면이 바뀌지 않는다면 바뀌지 않는 것이 정상인, 하나의 고정된 변수가 되어야 합니다.
- 1. 코드전환은 변환을 위한 키(열쇠)입니다. -입력도 출력도 코드전환에 지정된 코드로 일치되어 있어야 의미가 있습니다.
- 2. 코드전환은 일대일 변환만을 목표로 설계되었습니다. - 화면과 파이썬 내부와의 정보교환이 목적이지 코드와 코드사이의 변환을 의도한 것이 아닙니다.
코드전환을 이해하기 위한 핵심 포인트는 아래와 같습니다.
- 1. 터미날이 사용하는 코드(사람이 직접 쳐다 보는 창의 코드) - 기본코드(default code)
- 2. 파이썬 내부에서 사용하는 코드 - ucs-2
- 3. 파이썬에게 터미날의 코드를 알려주는 방법 - 기본코드전환(default encoding)
코드전환(encoding)의 존재 이유에 대하여
이외에도 여러 함수들이 관계되겠지만 주 관심을 두는 대상은 아래와 같습니다. 초보가 일반적으로 사용하는 코드이며 지금까지 여러 한글처리 방법에 논의된 메쏘드 혹은 함수중 공통적으로 나오는 것들입니다. 이외의 다른 테크닉은 논의의 대상에서 제외합니다. 초보들이 이해하지 못하는 방식으로 처리되는 한글 처리 방식은 (개인적인 판단으로) 잘못된 것입니다.
코드전환이 사용되는 메쏘드와 함수 : 문자열.encode(코드전환), unicode(문자열, 코드전환)
각 함수의 사용용도를 다음과 같이 추정합니다 - 출력을 위하여 임의로 사용하는 것은 옳지 않다는 것이 본인의 판단입니다. 어디까지나 저 자신만의 경험과 번역된 문서를 기초로 한 독단적인 판단입니다. 이러한 판단을 어디에서도 보지 못하였습니다.
- .encode(), .decode() : 파이썬을 위함. 파이썬이 사용함.
- 외부의 자료를 파이썬 내부의 자료로 내부적으로, 자동적으로 사용해야 하는 것입니다 - 출력을 위해 임의로 이 메쏘드들을 사용하는 것은 옳지 않습니다
- 사용을 하려면 전적으로 사용자의 책임이며, 프로그램의 호환성은 사라집니다.
- unicode() : 사람을 위함. 사람이 사용함.
- 자료의 처리를 위해 사용합니다 - 출력을 위한 용도로 사용하는 것은 옳지 않습니다
- unicode()호출은 내부적으로 다시 encode(), decode()를 나름대로 사용하는 것은 아닐까 추정하고 있습니다.
다음은 내부적으로 자동적으로 사용된다고 추정되는 메쏘드 혹은 함수에 대한 용어의 정의입니다.
- encode : 터미날의 코드를 파이썬의 내부코드(ucs-2)로 바꾸는 것 - (코드전환)
- decode : 파이썬의 내부코드(ucs-2)를 터미날의 코드로 바꾸는 것 - (코드해석)
- unicode: 터미날의 코드를 파이썬의 내부코드(ucs-2)에 직접 매핑해 넣는것 - (짝짓기)
간단히 이야기 해서 코드전환(encoding)은 터미날과의 입출력을 맞추어 주는 역할을 한다는 것입니다. 우리눈으로 보고 실제로 처리하기 위해서 필요한 변환 모듈을 모아놓은 것이 코덱입니다. 그리하여 각각의 창은 서로 다른 언어로 표시될 수 있습니다. 그러면 사람이 직접 쳐다 보는 코드가 어떤 것인가를 파이썬에 알려주는 방식이 필요한데 이것이 바로 코드전환(encoding)을 설정하는 것입니다. 코드전환은 두개가 아니라 한개입니다.
입출력이 다를 때는 실제로 자신만의 코덱을 만들 수도 있는데, mbcs로 입력받고 utf로 출력할 수 있으며 그 반대로도 할 수 있습니다. 그러나 그것은 코드변환의 문제입니다. 사람이 쳐다보고 있는 그 화면에서 입력할 때의 코드가 출력할 때 다른 코드로 나온다는 것은 의미가 없습니다. 혹시 디버깅이나 기술상의 이유로 보는 것은 전혀 논외의 문제입니다. 진짜로 이렇게 들어오는 코드와 출력되는 코드를 다르게 사용해 보고 싶으시면 자시만의 기본코드전환 코덱을 만들어 보세요 encoding 디렉토리의 mbcs, 또는 utf를 꺼내 decode와 encode를 원하시는 대로 작성해 보실 수 있습니다.
내가 보는 코드와 출력되는 코드가 일치하는게 정상인데 이것이 바로 encoding이라는 하나의 값입니다. 혹시 파일이 사람이 보는 창을 대신할 수 있습니다. 읽어 들일 때 utf로 읽어서 출력할 때 mbcs로 출력할 파일이라면 코드전환(encode)이라는 단어가 아니라 코드변환(convert)이라는 단어를 사용해야 합니다.
운영체제의 코드까지 고려하면 너무 복잡하므로 간단하게 다음과 같이 생각해 보았습니다. 절대로 혼동하지 말아야 할 것은 기본코드의 이름과 코드전환의 이름이 같다는 것입니다. 괄호사이의 mbcs와 utf-8은 코드전환입니다. 코드전환을 어디에 맞추어야 하는지 아래 그림을 보시면 아실 수 있는데.... 꼭 찝어 지적하자면 자신이 쳐다볼 창의 코드와 일치시켜야 합니다. 아주 다양하게 스스로 만들어서 사용하지 않을 것이라면 실제로 범용으로 사용되어야 할 창은 윈도우에서는 mbcs 리눅스에서는 utf가 최상이 아닐까 추측하고 있습니다.
encode---> <---encode 명령어 라인 인터프리터 ...(mbcs)...파이썬핵심...(utf-8)...IDLE 터미날의 기본코드 mbcs ucs-2 utf-8 <---decode decode--->
윈도우에서 대표적인 두 개를 들어 봅니다. 각 창은 자신만의 입출력 코드를 가지는 창을 가질 수 있습니다. 그러한 창들중 대표적인 창 둘을 들자면 tty를 흉내 내고 있는 명령어 라인 인터프리터와 IDLE입니다. 명령어 라인 인터프리터는 확실히 mbcs를 다루는 tty이고 IDLE은 비록 구이 환경이지만 tty를 흉내 내고 있는데, utf로 입출력되는 창입니다. 윈도우에서( 힘들여서 변환하는 수고 없이) 정확히 입출력되고 문자열 처리가 가능하려면 명령어 라인 인터프리터는 mbcs로 IDLE는 utf로 코드전환을 설정해야 합니다. 실제로 그것이 틀릴 때 나오는 상황에 대해서는 해킹 섹션에서 다루어 봅니다.
코덱의 용도
아직 유니코드로 통일 되지 않은 이 세계에는 수많은 코드 체계가 있습니다. 이러한 코드 체계를 파이썬의 핵심에서 다루고자 하는 시도가 코덱입니다. 코드전환은 encoding="코드전환"의 형태로 site.py, sitecustomize.py에 들어 있습니다. 이것을 기본코드전환이라고 하는데 위의 메쏘드나 함수의 '코드전환' 부분이 생략되면 기본으로 들어가는 값입니다. 만약 sitecustomize.py 가 존재한다면 site.py의 코드 전환을 덮어쓰는 고로 sitecustomize.py가 우선합니다. 혹시 site.py에서 코드전환을 고쳐도 차이가 나지 않는 다면 sitecustomize.py가 있는지 살펴 보셔야 합니다. 코드전환이라면 어떤코드에서 어떤코드로 변환한다는 것을 의미하는데, 그럼 그것이 무엇이냐 요약해서 설명하면 터미날의 문자열 에서 파이썬 내부의 문자열(ucs-2)로 코드전환 혹은 그 반대로 코드해석한다는 것입니다. 일대일 변환의 대상에서 하나는 반드시 파이썬핵심의 ucs-2입니다. 다자간 변환은 불가합니다 (불가능하다는 뜻이 아닙니다. 과연 불가능 한지의 여부는 본인도 모릅니다).
주운 정보: sitecusotomize.py 의 존재 이유 - 자신의 프로그래밍 환경을 재단하는 용도입니다. 그 중에 하나가 encoding값을 바꾸는 것이고 여기에다 자신이 원하는 것을 지정해 놓으면 자동으로 수입됩니다. 어찌보면, 도스의 config.sys 또는 auteoexec.bat 용도가 아닌가 생각합니다. 그렇지만 로케일까지 고려할 분은 주의하셔야 하는데, 로케일 설정은 site.py에서 자동으로 설정되기 때문입니다.
명령어라인 인터프리터의 경우에는 입력은 mbcs에서 ucs-2로 코드전환(.encode())한다고 가정하고 IDLE의 경우에는 utf에서 ucs-2로 코드전환(.encode())한다고 가정하고 있습니다. 물론 운영체제의 코드도 생각해야 할텐데 저 나름대로는 운영체제의 코드는 미가공 상태로 파이썬에 넘겨진다고 가정하고 무시합니다. 이것까지 고려하려니 너무 이론이 복잡해져서 이 글이 좀 정련을 겪고 나면 그 때 도입해 보도록 하겠습니다. 물론 역의 경우에는 코드해석(.decode())을 사용합니다. 이것은 파이썬 내부에서 자동적으로 이루어지고 있으므로 사용자가 임의로 .encode()를 사용한다면 자신의 책임하에, 스스로 이해하고서 사용하지 않으면 예상치 못한 행위에 봉착하게 되는데, 보통 사용자는 .encode("utf8")을 사용할 때 이 코드가 utf-8 이 된다고 생각합니다. 그렇지만 이런 단순한 생각의 뒤에는 맹점이 숨어 있는데 들어온 코드에 대한 가정이 전혀 없습니다. 여기에서 제대로 처리되는 이유는 내부적으로 파이썬이 먼저 "기본코드전환에해당하는문자열".encode(기본코드전환)으로 이미 한번 변환을 거쳤기 때문입니다. 만약 파이썬 내부에서 자동적으로 수행되는 코드전환에서 들어오는 코드를 정확하게 지정하지 않으면 .encode("utf")은 전혀 우리가 원하는 문자열이 되지 않습니다. 이것은 unicode()로 짝짓기해 진짜 유니코드로 변환된 것과는 전혀 다른 메카니즘입니다. 아주 정확하게 정의하자면 들어온 코드가 encoding코드이니 파이썬에 encoding이라는 키를 이용하여 ucs-2로 전환해 넣어라 하는 뜻입니다. 파이썬이 기본코드전환으로 정확하게 코드전환하고 나기만 하면 진짜로 코드 변환같이 사용할 수가 있어서, utf로 mbcs로 바꿀 수 있습니다. 똑 같은 키이기만 하면 (즉 mbcs, utf등등) 상관 없이 그대로 코드해석 됩니다. 이 모든 과정을 자동적으로 해 주는 것이 코덱이 하는 일이라는 것입니다. 이 과정에 뛰어들어 간섭하는 것은 전적으로 전문 프로그래머의 책임이 될 것입니다. - 초보들도 마구 뛰어 들고 있습니다. 그래서 봉착하는 문제들에 좌절하고 파이썬의 유니코드 기능 지원 미비를 탓하고 있습니다.
한글 코덱의 위치
이상의 설명으로 보면 한글 코덱이 euc-kr코드를 쓰는 터미날(파일도 마찬가지)을 위한 것임을 알 수 있습니다. euc-kr파일을 실행시키려면 당연히 euc-kr을 쓰는 겁니다. 그러나 euc-kr이 중심은 아닙니다. 중심은 utf-8에 있습니다. 따라서 한글코덱은 필수사항이 아니라 선택사항입니다. 이것이 필수 사항이라고 믿고 명령어 라인 인터프리터에서 기본코드전환을 euc-kr에 설정한 사람은 자신의 설정을 항상 기억하고 utf-8파일을 다루어야 합니다. 그리고 이 코덱은 이미 만들어진 euc-kr파일을 위한 것이어야 하며, 앞으로 만들어질 euc-kr파일을 위한 것이 되면 안됩니다. 즉 euc-kr로 파일을 만들면 스스로를 한국의 테두리에 묶는것이 되며 과거에 안주하는 것이 됩니다. utf가 태양이고, mbcs가 지구라면, euc-kr은 달입니다. 지구에서 달을 바라 볼수 있다면 태양에서 지구를 바라 볼 수도 있습니다. 한글코덱을 쓰기 위해서 euc-kr을 고집한다면 구이를 쓰기 위해서 utf-8을 고집할 수도 있습니다. 오히려 한글이 된다면 utf-8이 되어야 합니다. 표준은 과거를 위해서 결정되는 것이 아니라 미래를 위하여 있는 것입니다.
기본코드전환(default encoding)을 터미날의 코드에 일치시켜야 하는 이유
이 가정에는, 보시는 화면(창, 터미날, 파일)이 동일한 코드로 입출력이 된다는 것을 전제로 하고 있습니다. 그래서 어떤 코드전환을 사용하든 .encode()와 .decode()의 코드전환이 일치하면 그대로 터미날에 입력된 그대로 다시 출력됩니다. 그런데 터미날 값과 일치하지 않는 코드전환은 한글처리를 위해, 즉 길이 계산을 위해 unicode()로 문자열을 변환하면 예상치 못한 결과가 나옵니다. 터미날의 코드는 사람의 이해하는 코드이고 그 코드를 컴퓨터는 어떤 코드인지 이해하지 못합니다. 어떤 때는 변환자체가 안될 때가 있고 변환은 잘 되어도 길이뿐만 아니라 출력되는 문자열도 예상과는 틀린 경우가 발생합니다. 최초로 들어오는 값에 대하여 .encode()는 코드를 기본코드전환이라는 키로 파이썬 내부의 usc-2로 코드전환한 것이고 (당연히 코드해석 decode()해서 보아야하는 것이지 .encode()로 보는 것은 가능하다고 할지라도 유니코드 입출력의 메카니즘에 위배 됩니다.) 기본코드전환이 최초의 입력 코드를 제대로 지정하지 않고 있다면 다시 꺼내 보는데는 막대한 수고를 필요로 합니다. unicode()는 기본코드전환에 맞추어 실제 유니코드에 짝짓기해서 넣은 값입니다. 그래서 유니코드로 짝짓기 된 값은 u"실제유니코드(ucs-2)"로 다르게 저장되어 있습니다. 만약 여기에서 a=u"mbcs문자열"이라는 서술문으로 a가 유니코드가 되어 주기를 기대하는 것은 입출력 메카니즘을 이해하지 못하는 데서 오는 잘못된 요구라는 것입니다. 이 서술문의 의미는 a=unicode("mbcs문자열", "unicode_escape")와 같습니다. 그러므로 눈으로 이해 할 수 없는 글자가 되어 버립니다. 이럴때는 unicode("mbcs문자열", "mbcs")라고 명시적으로 지정해 넣어 주어야 눈으로 해석할 수 있습니다. 그러므로 만약 u""를 사용해 보고 싶으면 기본코드전환을 unicode_escape로 놓으시면 입력이 됩니다. 문제는 unicode_escape를 지원하는 터미날이 없다는 것인데 지금까지의 IDLE 패치 방법덕분에 해결방법이 있습니다. 단 이러한 표현이 필요한 것인지는 의문입니다.
그래서 각각의 경우에 제대로 된 값을 얻으려면 생략된 "코드전환"을 명시적으로 지정해 주어야 합니다. 즉 사람이 보는 화면의 코드에 일치시키지 않는다면 원하는 값을 얻기 위해 불필요한 수고를 해야 한다는 뜻입니다.
터미날은 mbcs이고 입력되는 파일은 utf 그리고 기본 코드전환은 unicode_escape라면 혼란의 극에 달합니다. 이런 조합은 근본적으로 코덱의 능력을 남용한 것이라 판단합니다. 내부적으로 어떻게 변환해야 원하는 값을 얻을 지는 머리가 복잡해 생략하고 싶지만 간략하게 살펴보겠습니다.
코드전환일치의 문제 해킹
지금부터는 해킹수준입니다. 이러한 코딩방법은 절대로 권장되지 않습니다.
mbcs인가 utf인가
encoding은 하나이며 같은 키로 코드전환, 코드해석을 하는 것이라고 가정하였는데, 실제로 입력과 출력이 다른 코드가 한 화면에서 사용되고 있을 경우가 있습니다. 이 문제는 너무 복잡한 문제입니다. 그래서 단 두개의 대표적인 코드전환을 가지고 위의 이론을 좀 더 연구해 봅니다. mbcs는 윈도우를 쓰는 한 거부할 수 없는 선택이고 utf는 구이들의 대부분이 utf-8로 처리하기 때문에 선택하였습니다. 즉 윈도우에서 구이를 사용하려면 필연적으로 mbcs와 utf에 마주치지 않을 수 없습니다. 또 새로나오는 파이썬 라이브러리들은 utf-8을 예상하고 만들어지고 있습니다.
1. 명령어 라인 인터프리터와 IDLE
명령어 인터프리터의 encoding을 utf로 놓아 보고 실행해 보시면 입출력은 이상이 없읍니다. 입력된 그대로 출력됩니다. 그러나 unicode()해 보면 유니코드 에러에 봉착합니다. 어떤 에러인고 하니 mbcs로 들어온 문자열을 (사람만 이 코드인줄 알고 파이썬은 utf-8로 보고 있으므로) 유니코드 영역에 짝짓기에 실패 합니다. 혹시라도 코드영역이 충돌하지 않는다면 괴이한 글자로 입력될 수도 있지만 그 때의 len()함수의 결과값은 보장받을 수 없습니다.
이런 상황이라면 그럼 어떻게 입력하고 출력하고 처리할 수 있는가? unicode(문자열, "코드전환")에서 생략되었던 코드전환(utf-8)을 명시적으로 mbcs라고 지정해주면 사람이 볼수 있는 유니코드 문자로 정확하게 짝짓기 됩니다. 그리고 출력할 때는 명시적으로 문자열.encode("코드전환")에서 코드전환을 반드시 명시적으로 "mbcs"라고 지정해주어야 비로서 우리가 알수 있는 문자로 출력이 가능해집니다.
결론을 이야기 하자면 기본코드전환을 이리저리 바꾸는 것은 쉽게 이야기 해서 터미날을 이리저리 바꾸는 것과 똑 같습니다. 자신이 쳐다 보고 있는 터미날이 카멜레온처럼 시시각각 코드를 바꾸지는 않을 것입니다. 특별하게 새로운 입출력 터미날을 정의할 것이라면 코덱을 상속받아 자시만의 터미날을 구성하여 사용하여야 할 것입니다(본인만의 추측일 따름이니 혹시라도 이 정보에 매달리지 마시길 바랍니다).
IDLE에서 기본코드전환을 mbcs로 해 놓았을 경우에는 좀 특별하게 작동하는데, 먼저 tkinter가 윈도우의 mbcs를 "utf"로 변환하고 이렇게 변환한 값을 IDLE에 넘겨 준다고 생각하는데, IDLE은 당연히 들어온 입력값을 "mbcs코드전환된문자열".encode()로 변환합니다. 기본코드전환이 "mbcs"인고로 이렇게 전환된 코드는 출력해도 알아 볼 수 없습니다. 출력은 utf-8로 합니다. 그래서 위의 이론대로 기본코드전환에 상관없이 입출력 된다는 이론은 들어 맞지 않습니다. 그래서 아예 다른 코드전환으로 바꾸어서, 예를 들어 unicode_escape로 바꾸어 보면 그에 맞게 unicode_escape로 저장하고 있습니다. 즉, 입력되는 터미날의 코드를 기본코드 전환으로 받아들여 저장한다는 것입니다. 물론 출력은 원하는 문자가 아닙니다.
죽어도 출력을 해 보려면 print unicode("mbcs코드전환된문자열").encode("utf")를 수행해 보시면 입력될 때의 문자가 다시 나옵니다. 실제로는 패치를 해서 눈에 보이게 출력할 수도 있고 저장되게도 할 수 있으며 제대로 처리되게 할 수도 있지만 IDLE의 전 체계를 이해하지 못하는 고로 오히려 원래 원했던 유니코드 한글 처리의 메카니즘에 혼동을 줍니다. 실제로 mbcs를 지원하도록, 또는 euc-kr을 지원하도록 패치해야할 이점이 없다고 저는 보고 있습니다. 정 원한다면 패치를 통해서가 아니라 원하는 터미날을 흉내 내주는 프로그램을 직접 구성하는 것이 훨씬 좋을 것입니다.
그냥 코드 테스트라면 IDLE에서는 utf-8일때 가장 정확하게 tty를 흉내내 줍니다. mbcs를 쓰고 싶으시면 파이썬 윈이 가장 훌륭한 해결책입니다.
2. 유니코드 미지원 편집기(mbcs만으로 입출력하는 편집기)
(tkinter, pyqt도 마찬가지라고 추론하는바인데) pygtk 프로그램을 코딩할 때 윈도우의 편집기가 mbcs만을 지원한다고 합시다. 이 예는 오직 코드의 이해를 도울 목적이지 출력방법을 연구해보고자 하는 것이 아닙니다. 실제로 이것을 써먹어야 한다면 아주 특별한 프로그래밍을 하고 있는 것이 됩니다. pygtk에 출력하려면 utf-8 코드를 보내 주어야 합니다. 어디에 코드 전환을 설정하여야 하는지 결정할 수 있습니까? 아니면 코드전환과 관계없이 명시적으로 옵션을 설정하면 해결할 방법이 있습니까? mbcs이든 utf이든 코드전환과 상관없습니까? 단순히 표면적인 현상만 살펴 봅니다. 이러한 행태가 나타나는 이유는 본인의 능력 부족으로 자세하게 설명이 불가능합니다.
- 1. 기본코드전환이 mbcs일 경우(입력에 설정) : "mbcs문자열".encode("utf-8")로 출력가능. 내부적으로 이미 .encode()가 사용되어 코드전환됩니다. 생략된 코드전환에서 기본코드전환이 정확하게 설정되어 전환되었으므로 다시 utf-8로 변환이 가능합니다.
- 2. 기본코드전환이 utf일 경우(출력에 설정) : uniocode("mbcs문자열", "mbcs")로 출력가능.
- 3. 기본코드전환이 제 3의 코드전환인 경우 : uniocode("mbcs문자열", "mbcs").encode("utf")로 출력가능.
(확실한 것은 엄청나게 불편한 과정을 거쳐야 한다는 것입니다; 왜 이러한 접근법을 사용하는가? 이유는 명령어 라인 인터프리터에서는 이런 방식을 사용하지 않으면 출력해 볼 수 없습니다. 이것은 자신의 터미날이 고정되어 있기 때문에 피할 수 없습니다. 그러니까 터미날과 다른 코드를 사용할 때는 어쩔 수 없습니다. 그러나 이렇게 꼬아서 사용하는 방법은 좋지 않습니다.)
여기에서도 어차피 출력할 거라면 출력에 맞추어 encoding을 맞추어 두는 것이 더 유리함을 알 수 있습니다. 한글 처리를 위해 unicode()는 필수 불가결하기 때문입니다. 테스트는 콘솔에서 해 보되, 무엇보다도 본격적으로 프로그램을 짜려면 유니코드 지원 편집기를 사용하는 편이 가장 확실한 방법입니다. 그렇게 되면 이런 복잡함도 순식간에 해결됩니다. 본인의 판단으로는 이것이 정석이라고 생각합니다.
3. 구이의 선택 문제
본인이 처음 구이의 선택 문제에 고민했던 것은 한글코드 출력의 문제였습니다. 그런데 이러한 메카니즘을 이해하고 나니 구이의 선택조건에서 한글 구현 문제는 장애가 되지 않는 것이었습니다. 확실한 방법은 유니코드 지원 편집기를 사용하는 것입니다. 이러한 기능을 가진 편집기는 스스로가 일종의 터미날이 되어 주므로 출력될 구이의 코드에 맞추어 저장하기만 하면 됩니다. 처음에 매력을 가졌던 wxpython의 매력의 하나(편리한 한글입출력)는 그래서 상실하게 되었습니다. 구이 선택에서 한글문제가 빠지고 나니 정말 무엇을 선택할지 다시 고민입니다. tkinter도 괜찮고 pygtk도 멋있습니다. 물론 wxpython도 정감이 갑니다.
윈도우에서 처리하기에는 mbcs가 유리하고 나와 있는 각종 라이브러리들은 utf-8이 유리합니다. 코드전환은 고정시켜야 하고 처리해야할 문서들(각각의 터미날)이 다 각각 다른 코드를 사용한다면 정말 어떻게 처리해야 할지 너무 복잡합니다.
적어도 그동안 고민했던 구이에서의 한글 입출력 문제는 해결되었지만, 여전히 mbcs와 utf사이의 선택의 기로는 존재하고 있습니다. 플랫폼사이의 호환성 문제가 계속해서 문제가 되고 있는 것인지도 모르겠습니다.
구이의 선택에는 라이브러리의 질, 지원되는 문서의 양과 질, 라이센스 문제등이 고려되어야 하겠지만 이 글에서의 목적은 아니므로 생략합니다. 여력이 된다면 어떤 구이를 선택해야 하는지도 연구해 보아야 할 과제입니다.
아직도 해결하지 못한 문제
지금부터는 반드시 다루어야할 문제이나 능력부족으로 다루지 못하는 부분들입니다. 능력되시는 분들의 건투를 요망하는 부분입니다.
1. 왜 코드전환에 unicode가 없는 것일까?
이렇게 해도 아직 만족이 되지 않는 것은 여전히 unicode함수를 쓰지 않을 수 없다는 것입니다. 파이썬 내부적으로는 확실히 유니코드 문자를 쓰고 있음에도 왜 굳이 unicode()를 사용해야 하는 것일까. 파이썬 인터프리터의 선택사항 중 -U가 있다는 것을 아시면 u"유니코드"의 형태를 그냥 저장할 수 있으므로 unicode를 그대로 사용할 수 있을텐데 하는 의문이 듭니다. 즉 번거롭게 unicode()를 사용하지 않아도 된다는 것인데....
지금까지의 이론상으로 encoding에 unicode가 있어야 할 필요는 없습니다. 그냥 쓰면 될것을 굳이 encode(), decode()할 필요가 없지 않습니까? 그래도 간절히 원하는 바가 있어 lib/encoding 디렉토리를 살펴 보니 unicode_escape, raw_unicode_escape가 있는데 실제로 우리가 그렇게 천하 통일을 원하는 unicode라는 코드전환은 역시 없습니다. 그나마 비슷하게 있는 것은 끝에 _escape를 달고 있는데 그것을 보니 해답이 생각났습니다. 이유는 우리의 터미날이 아직까지 유니코드 터미날이 아니다라는 데 있습니다. 유니코드 (ucs-2)는 아스키와 충돌합니다. 아스키를 피해서 만들어진 코드가 아니므로 우리가 작성하는 프로그래밍 소스는 안타깝게도 유니코드와 충돌하는 바 당연히 인터프리터가 해석할 수 없습니다. 즉 해결방법은 유니코드에 탈출문자를 붙여서 코딩하는 방법이라는 것인데 실제로 이렇게 지원해주는 에디터를 아직 보지 못하였습니다. 이것은 단순히 코드변환만으로 저장될 파일이 아니라 유니코드 문자열에 해당하는 부분을 하나씩 해석하여 탈출문자로 코딩하여 저장하여야 하는 것이므로 특별히 고안되어야 할 것입니다.
a=u"한글" 이라는 서술문을 수행해 보고 싶어서 encoding=unicode_escape로 하고 -U로 하면 코드전환이 죽어도 ascii로만 설정되고 있습니다. -v로 살펴 보면 이상하게도 import site 자체를 하지 않습니다. 즉 파이썬에서는 -U라는 선택사항이 주어지면 유니코드 터미날과 입출력을 하는 것으로 가정하기 때문에 import site를 하지 않는 것이라고 생각됩니다. 그럼에도 불구하고 여전히 남는 의문 사항은 기본 코드전환을 이 때에 ascii로 하는가 하는 것입니다. 위의 이론대로라면 억지로 유니코드를 집어 넣어도 decode()를 어떻게 하라는 것인지...아직도 의문입니다.
2. 소소코드를 일일이 고쳐서 한글화 해야 하는가?
너무도 기쁜 마음으로 파이썬 메가 위젯을 예제중 하나인 baloon.py에 있는 영어 문자열을 한글로 바꾸어 보았더니 입력도 되고 풍선도움말 까지...순간, 저 많은 코드를 다 이렇게 고쳐야 하는가 하는 의문이 들었는데, 번역된 문서중에선 메시지 카탈로그에 대한 개념을 읽어 본 기억이 났습니다. 파이썬 메가 위젯이 메시지 카탈로그까지 염두에 구성되었으면 좋겠습니다. 능력이 닿지 않아 지원하는지 안하는지 확인해 볼 수는 없습니다.
3. 클립보드를 이용한 데이타 교환은 어떻게 하는가?
클립보드 사이의 데이타 교환이 비트맵이 아닌 코드인 이상, 피할 수 없는 문제인데, pygtk, tkinter등에서 끌어 놓기 한 데이타들이 상이한 행태를 보이는 것은 "끌어 놓기" 처리 사이에 코드 변환부분이 정확하게 정의되지 않는 문제때문이라고 생각됩니다. 어떻게 인터페이스를 정의해야 하는지에 대하여 역시 능력 부족을 다루어 보지 못합니다.
4. 그럼 리눅스에서는 어떻게 한글을 사용할 까?
이론적으로 mbcs터미날이 유닉스상에 존재하지 못할 이유는 없겠지만, 보시다시피 mbcs는 윈도우에만 가치가 있습니다. 실제로 구이 프로그래밍하는데는 utf-8을 설정하지 않으면 상당한 수고를 해야 함을 보았습니다. 그럼 리눅스에서 utf-8로 코딩하는 것이 이점이 있는가? euc-kr이라는 한글 코덱은 리눅스에 필수 불가결한 존재인가? 능력이 안되는 관계로 모든 걸 테스트 해보지 못합니다. 관심있는 분들은 제 질문의 요지를 확실히 이해하리라 생각합니다. 이 글을 읽어 보셨다면 테스트의 기준이 서시리라 믿습니다. 확실한 기준을 세우고 테스트하면 확실한 답이 나오겠지요. 테스트해 보십시오. euc-kr없으면 한글을 사용할 수 있는지 없는지, 어떤 문제가 있는지를..........
5. print와 echo의 차이는 무엇인가?
여기에는 로케일이 작용하는 거 같은데 메카니즘을 파악을 못하였습니다. tty형 터미날(대표적으로 IDLE이나 명령어라인 인터프리터)에서 코드 연습을 하거나 작업을 할 때, a="한글" 을 타자하고 엔터하면 들어간 값이 다시 출력되어 나옵니다. print a 라고 타자하면 a가 가진 값이 출력되 나옵니다. 아스키의 경우에는 출력되는 양자의 값이 같아서 친숙한데, 한글은 그렇지 않고 백슬래쉬가 붙은 코드들이 일렬로 늘어서서 출력되는 것을 볼수 있습니다. 이것이 한글로 출력되는 것이 정상일 거 같은데 뭔가 잘못된 것은 아닌가 이런 생각을 하게 됩니다. 파이썬에서의 유니코드 입출력에 대하여 연구하면서 두 개의 용도가 다르다는 생각을 하게 되었는데, echo로 나오는 값은 내부의 코드 형태를 보여주는 것이고, print로 나온 값은 사용자에게 정보를 주고자 하는 목적이 아닌가 추측해 보았습니다. 만약 echo의 출력값과 print의 출력값이 같기를 원한다면 터미날을 그렇게 구성해서 사용해야 하는 것이라고 생각해 봅니다. IDLE이 나름대로 터미날을 구성해서 사용하는 것을 보면 가능할 것 같습니다. 코덱을 이리저리 건드려 보면 해결책이 나올 것도 같습니다.
불확실한 결론으로 마치며
참으로 되도 않는 결론으로 마치게 됩니다.
- encode()는 전문가 아니면 사용하지 말자. (코덱 수준의 프로그래밍에만 사용하는 것이다)
- unicode()는 출력용이 아니라 처리용이다. (길이 계산, 조각썰기 등에 사용)
- 기본코드전환은 자신의 출력 터미날에 맞게 지정해 주자 - euc-kr을 고집할 필요가 없다.
- 프로그래밍 파일을 작성하려면 utf-8로 작성하자.- euc-kr로 작성하는 것은 불가하다.
- 1. 나는 어떤 코드를 사용하는 창을 보고 있는가.
- 2. 입력되는 파일과 출력파일의 코드가 다르지는 않은가.
사실은 예제까지도 준비하고 있었는데 그러다 보니 정말 완벽한 지침서가 되어 버리는 것 같아서 포기하였습니다. 어차피 지금은 이론을 구성하고 있는 것이고 이 글을 읽는 사람들의 많은 참여로 다시 무장할 준비를 하고 있는지라 확실한 결론을 내어 버리면 이제 시작하는 초보들에게 잘못된 길로 인도할 수도 있다는 중압감 때문이었습니다.
이상으로 복잡하기 이를데 없는 윈도우에서의 유니코드 한글처리문제를 드러나는 표면 현상의 괴리들을 보고서 정리하였습니다. 본인은 이렇게 고민하고 복잡하게 생각하고 있는데 다른 분들은 별로 곤란을 느끼지 않는 것 같습니다. 아마도 윈도우에서의 파이썬 프로그래밍이 활성화 되지 않은 때문인것은 아닌가 생각합니다. 리눅스에서는 아무 문제가 없는 것인지도 모릅니다. 그렇지만 자신의 프로그래밍 환경을 다른 플랫폼으로 새로운 구이환경으로 이동시킬 때 반드시 지금 본인이 논의한 코드 문제에 봉착하리라 생각합니다. 위에 은색 색칠해 놓은 부분은 결론 부분입니다. 한글문제로 고민하시는 분들은 그대로 설정하시는 것을 권장합니다.
수정 johnsonj 2002.01.01 파이썬 만세!!!
[출처] 파이썬 유니코드 한글처리 문제|작성자 푸른하늘
출처 : http://blog.naver.com/silkyesk/10013408596
'Language > Python' 카테고리의 다른 글
특정 PORT Check (0) | 2016.06.14 |
---|---|
install PyMySQL (0) | 2015.07.21 |
crontab+python3 (0) | 2015.06.30 |
python??? (0) | 2015.06.22 |
RND(Right! Now! Develop!) Study - Python Step. 02 자료형_02 (0) | 2014.08.17 |