86

Click here to load reader

Character Encoding in python

Embed Size (px)

Citation preview

Page 1: Character Encoding in python

강 대 성[email protected]

Character Encoding in Python

Page 2: Character Encoding in python

발표자 소개 - 강대성컴퓨터 전공, 경제 부전공

게임회사 3년 - MMORPG 서버 개발통신회사 2년 - 인사 관리 시스템 금융회사 6년 - 해외선물, FX거래 시스템

록앤올(김기사) 2년 - 교통정보 분석, 미래 속도 예측피플펀드컴퍼니 2015.09 ~ - 기술총괄

현)대한아이스하키협회 심판 2007~

Page 3: Character Encoding in python

발표 내용

Encoding의 기초UTF-8 UTF-16

ASCII EUC_KR

고통을 해결한 사례

고통과 멀어지는 팁

Encoding 에 익숙해지기

Page 4: Character Encoding in python

다음 중 3가지 이상을 알고 있다면...?

U+Unicode != UTF-8

BOMUTF-16LE(BE)

Two string types in python ‘unicode’ ‘str’

Page 5: Character Encoding in python

독일 쇼핑몰에서 주문을 하고, 배송을 시작할 때 쯤 메일왔습니다.

독일어라 알아보진 못하지만, 글자가 깨졌습니다.

Page 6: Character Encoding in python
Page 7: Character Encoding in python

왜 이럴까?

Page 8: Character Encoding in python

약속(Encoding)을 제대로 지키지 않음.

Page 9: Character Encoding in python

약속을 이해하고,

Python에서 약속을 어떻게 다루는지

어려움이 생겼을 때는 어떻게하는지?

Page 10: Character Encoding in python

Encoding

Page 11: Character Encoding in python

자료 : http://parks.seoul.go.kr/template/common/park_info/park_intro.jsp?park_id=namsan&fclass_num=794&mclass_num=1230

Page 12: Character Encoding in python

봉수 : 전투 상황을 5가지 신호로 전달

자료 : http://ko.wikipedia.org/wiki/봉수

http://parks.seoul.go.kr/template/common/park_info/park_intro.jsp?park_id=namsan&fclass_num=794&mclass_num=1230

평상시 1

국경에나타남 2

국경근접 3

국경침범 4

전투중 5

Page 13: Character Encoding in python

Encoding?

전달하려는 내용을 부호화

Page 14: Character Encoding in python

문자나 기호들의 집합을 저장하거나 통신에 사용할 목적으로 부호화하는 방법

EncodingCharacter

자료 : http://ko.wikipedia.org/wiki/문자_인코딩

Page 15: Character Encoding in python

저장, 통신을 하기 위해서 2진수가 기본

1101 0010 1010 0001

편의상 2진수 4개를 하나로 합쳐 16진수로 표현

0xD2A1

Page 16: Character Encoding in python

저장장치에 ‘PyCon’를 0x50 79 43 6F 6E 로 저장

Network으로 ‘강대성’을 0xEA B0 95 EB 8C 80 EC 84 B1으로 전송(UTF-8)

0xB0 AD B0 EB BC BA으로 전송 (EUC-KR)

Example

Page 17: Character Encoding in python

Morse Code (모스 부호, 1844) -••---•-•

FM 라디오 방송

Unicode

EUC_KR

봉수

Character Encoding 이 맞는 것은?

Page 18: Character Encoding in python

Character Encoding

ASCII, EBCDIC ... ASCII : American Standard Code for Information Interchange

EBCDIC : Extended Binary Coded Decimal Interchange Code

EUC_KR, CP949 ... EUC : Extended Unix Code, CP : Code Page

Unicode, UTF-8, UTF-16, UTF-32 … Unicode는 인코딩이 아님

http://b.mytears.org/2005/01/101

Page 19: Character Encoding in python

Encoding에 따른 동일한 문자 표현 방법

Page 20: Character Encoding in python

H i 똠 방 각 하

ASCII 0x48 0x69

EBCDIC 0xC8 0x89

EUC_KR 0x48 0x690xA4D4A4A8A4C7A4B1채움/ㄸ/ㅗ/ㅁ

0xB9E6 0xB0A2 0xC7CF

CP949 0x48 0x69 0x8C63 0xB9E6 0xB0A2 0xC7CF

Unicode U+48 U+69 U+B620 U+BC29 U+AC01 U+D558

UTF-8 0x48 0x69 0xEB98A0 0xEBB0A9 0xEAB081 0xED9598

UTF-16BE 0x0048 0x0069 0xB620 0xBC29 0xAC01 0xD558

UTF-16LE 0x4800 0x6900 0x20B6 0x29BC 0x01AC 0x58D5

같은 문자라도 인코딩에 따라

다르게 부호화 되고,

일부는 표현이 불가능하다.

Page 21: Character Encoding in python

동일한 내용을 Encoding에 따라 해석 0x50 0x79 0x43 0x6F 0x6E 0x2E 0x4B 0x52

ASCII P y C o n . K R

UTF-8 P y C o n . K R

UTF-16BE 偹 䍯 渮 䭒

UTF-16LE 祐 潃 (not valid) 剋

부호를 어떤 인코딩으로

해석을 했냐에 따라 다르게 해석된다.

Page 22: Character Encoding in python

UTF-8

ASCII

CP949

EUC-KR

ASCII

Page 23: Character Encoding in python

Unicode

Page 24: Character Encoding in python

Unicode전세계 문자, 기호를 Codepoint에 매칭. 한글, 타이문자

많이 쓰이는 이모티콘도 정의 ex) Pile of Poo(U+1F4A9, )

CodePoint : U+로 표현. ASCII영역은 U+0000~U+007F 한글 : 초성/중성/종성, 자음/모음, 완성글자 영역이 있음.

Page 25: Character Encoding in python

Unicode != UTF-8 U+AC15 != 0xEA B0 90

Unicode : 문자를 CodePoint에 매칭시킴 일반적으로 전송&저장을 위해 사용하지 않음. UTF-8 : Unicode의 전송&저장을 위한 인코딩 방법

Page 26: Character Encoding in python

왜 UTF-8?1. 모든 Unicode Codepoint 를 다룰 수 있다.

2. Unicode를 Encoding했을 때 NULL 이 포함되지 않음. C에서 strcpy()를 사용할 수 있음.

3. ASCII text는 UTF-8 text가 될 수 있음.

4. 주요한 문자들은 1~2bytes로 표현가능. (한글은 3 bytes)

5. 일부 바이트가 유실되어도, 다음 시작 byte를 알아낼 수 있다. https://docs.python.org/3/howto/unicode.html

Page 27: Character Encoding in python

Web Encoding

UTF-8 : 84.0%ISO-8859-1(서유럽어) : 8.1%

http://w3techs.com/technologies/overview/character_encoding/allhttp://ko.wikipedia.org/wiki/ISO/IEC_8859

Page 28: Character Encoding in python

Encoding in HTTP, HTML, E-mail ... HTTP Header : Content-Type:text/html; charset=utf-8

HTML Header : <head><title>파이콘 한국 2015</title> <meta charset="utf-8"> </head>

HTML Header : <head><meta http-equiv="Content-Type" content="text/html; charset=euc-kr" />

</head>

E-mail : Content-Type: text/plain; charset=UTF-8Content-Transfer-Encoding: base64

Page 29: Character Encoding in python

이제 Python 이야기Character Encoding in Python

Page 30: Character Encoding in python

Two string types in Python 2/3

Python2 / str : 'abc가나다' unicode : u'abc가나다'

Python3 / bytes : b'abc가나다’ str : 'abc가나다'

Page 31: Character Encoding in python

Two string types in Python 2/3Python 2

>>> str1 = 'PyCon.KR 2015 강대성'>>> type(str1)<type 'str'>>>> len(str1)23

>>> uni_str1 = u'PyCon.KR 2015 강대성'>>> type(uni_str1)<type 'unicode'>>>> len(uni_str1)17

Page 32: Character Encoding in python

Two string types in Python 2/3Python 3

>>> bytes1 = b'PyCon.KR 2015 \xea\xb0\x95\xeb\x8c\x80\xec\x84\xb1'>>> type(bytes1)<type 'bytes'>>>> len(bytes1)23

>>> str1 = 'PyCon.KR 2015 강대성'>>> type(str1)<type 'str'>>>> len(str1)17

Page 33: Character Encoding in python

Encode / Decode 용어 익히기

Unicode로 표현된 데이터‘가나다라abcd’

ex)2 / unicode, u’PyCon \uac15’3 / str, ’PyCon \uac15’

저장, 통신이 가능한 데이터10101101110010101010101

ex)2/str, ’PyCon \xea\xb0\x95’3/bytes, b’PyCon \xea\xb0\x95’

Decode

Encode

Page 34: Character Encoding in python

unicode ⇔ str in python2 unicode.encode() => str str.decode() => unicode

>>> unistr = u'PyCon.KR 2015 강대성' >>> unistr u'PyCon.KR 2015 \uac15\ub300\uc131'

>>> unistr.encode('UTF-8')'PyCon.KR 2015 \xea\xb0\x95\xeb\x8c\x80\xec\x84\xb1'

>>> unistr.encode('EUC-KR')'PyCon.KR 2015 \xb0\xad\xb4\xeb\xbc\xba'

Page 35: Character Encoding in python

unicode ⇔ str in python2 unicode.encode() => str str.decode() => unicode

>>> str1 = 'PyCon.KR 2015 강대성' >>> str1 'PyCon.KR 2015 \xea\xb0\x95\xeb\x8c\x80\xec\x84\xb1'

>>> str1.decode('UTF-8')u'PyCon.KR 2015 \uac15\ub300\uc131'

Page 36: Character Encoding in python

str ⇔ bytes in python3

str.encode() => bytes bytes.decode() => str

>>> str1 = 'PyCon.KR 2015 강대성' >>> str1 'PyCon.KR 2015 강대성'

>>> str1.encode('UTF-8')b'PyCon.KR 2015 \xea\xb0\x95\xeb\x8c\x80\xec\x84\xb1'>>> str1.encode('EUC-KR')b'PyCon.KR 2015 \xb0\xad\xb4\xeb\xbc\xba'

Page 37: Character Encoding in python

str ⇔ bytes in python3

str.encode() => bytes bytes.decode() => str

>>> bytes1 = b'PyCon.KR 2015 \xea\xb0\x95\xeb\x8c\x80\xec\x84\xb1' >>> bytes1 'PyCon.KR 2015 \xea\xb0\x95\xeb\x8c\x80\xec\x84\xb1'

>>> bytes1.decode('UTF-8')'PyCon.KR 2015 강대성'

Page 38: Character Encoding in python

간단한 연습유럽 여행을 함께 하기로 한 친구 4명이 각각 좋아하는 여행지와 소요 예산을 text 문서로 저에게 전달해주었습니다. 이것을 하나의 파일로 합치면서 정렬하기 1.csv 나폴리, 3일, EUR 500 2.csv München, 2Days, €400 3.csv 로마, 4일, 300유로 4.csv London, 3D, £300

Page 39: Character Encoding in python

Python3 Code

filenames = ['1.csv','2.csv','3.csv','4.csv']

datas = []for filename in filenames: f = open( filename, mode='rb' ) datas.append( f.read() ) f.close()datas.sort()f_write = open( 'summary.csv', mode='wb' )for data in datas: f_write.write(data)f_write.close()

Page 40: Character Encoding in python

pi@raspberrypi ~/pycon $ cat summary.csvLondon, 3D, ▒300M▒nchen, 2Days, ▒400▒θ▒, 4▒▒, 300▒▒▒나폴리, 3일, EUR 500

다 깨졌다!

Sort도 정상이지 않음

Page 41: Character Encoding in python

원인 : 인코딩을 고려하지 않음

1.csv 나폴리, 3일, EUR 5002.csv München, 2Days, €4003.csv 로마, 4일, 300유로4.csv London, 3D, £300

( UTF-8 ) ( ISO-8859-15 ) ( EUC-KR ) ( ISO-8859-1 )

Page 42: Character Encoding in python

Tip #1 : Unicode Sandwich

Unicode(In Python)

Byte( Storage, Network )

Byte( Storage, Network )

Page 43: Character Encoding in python

files = [('1.csv', 'UTF-8'),('2.csv','ISO-8859-15'),('3.csv','EUC-KR'),('4.csv','ISO-8859-1')]

f_write = open( 'summary.csv', mode='wb' )datas_unicode = []for file in files: f = open( file[0], mode='rb' ) data_r = f.read() data_decoded = data_r.decode( file[1] ) datas_unicode.append( data_decoded )

datas_unicode.sort()

for data_unicode in datas_unicode: data_w = data_unicode.encode('utf-8') f_write.write( data_w ) f.close()f_write.close()

Byte

Byte

Unicode

Page 44: Character Encoding in python

pi@raspberrypi ~/pycon $ cat summary.csvLondon, 3D, £300München, 2Days, €400나폴리, 3일, EUR 500로마, 4일, 300유로

Page 45: Character Encoding in python

Tip #1 : Unicode Sandwich(remind)

Unicodes(In Python)

Bytes( Storage, Network )

Bytes( Storage, Network )

Page 46: Character Encoding in python

인코딩 문제를 해결한 사례들...

Page 47: Character Encoding in python

소스코드에 한글을... ?

- Python Interpreter는 소스코드(*.py)를 입력으로 받는 프로그램

- 입력되는 소스코드에 Encoding이 명시되어 있어야 함.

Page 48: Character Encoding in python

Source Code Encoding

Python3

- # -*- coding: encoding -*-

- Default : UTF-8

https://docs.python.org/3/tutorial/interpreter.html#source-code-encoding

Python2- UTF-8 BOM : UTF-8

- # -*- coding: encoding -*-

- Default : ASCII

https://docs.python.org/2/library/codecs.html#standard-encodings

https://docs.python.org/2/tutorial/interpreter.html#source-code-encoding

Page 49: Character Encoding in python

BOM(Byte Order Mark)Unicode Codepoint : U+FEFF UTF-8 : EF BB BF ( ISO-8859-1 :  ) UTF-16 BE(Big Endian) : FE FF UTF-16 LE(Little Endian) : FF FE

http://en.wikipedia.org/wiki/Byte_order_mark

Page 50: Character Encoding in python

Standard I/O도 Encoding과 함께

Page 51: Character Encoding in python

Standard Output Encoding in Python2> cat encodingtest.py# -*- coding: UTF-8 -*-import sys

print 'Standard output encoding is', sys.stdout.encodingprint u'Test #1 ', u'PyCon 2015'print u'Test #2 ', u'강대성'

> python encodingtest.pyStandard output encoding is UTF-8Test #1 PyCon 2015Test #2 강대성

Encoding is UTF-8 = Terminal Encoding

Page 52: Character Encoding in python

> python encodingtest.py > output.txtTraceback (most recent call last): File "encodingtest.py", line 6, in <module> print u'Test #2 ', u'강대성'UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

> cat output.txtStandard output encoding is NoneTest #1 PyCon 2015Test #2

Redirect stdout

Encoding is None = sys.stdout.encoding

Page 53: Character Encoding in python

Process를 실행하면 3개의 파일이 open 됨0(Standard Input), 1(Standard Output), 2(Standard Error)

run “python”pi@raspberrypi /proc/11568/fd $ ls -llrwx------ 1 pi pi 64 Aug 23 15:46 0 -> /dev/pts/1lrwx------ 1 pi pi 64 Aug 23 15:46 1 -> /dev/pts/1lrwx------ 1 pi pi 64 Aug 23 15:46 2 -> /dev/pts/1

/proc/processnumber/fdLinux 시스템에서 각 프로세스들의 열린 파일들을 볼 수 있음.

Page 54: Character Encoding in python

Redirect 하면...?

run “python > test.output”pi@raspberrypi /proc/11588/fd $ ls -llrwx------ 1 pi pi 64 Aug 23 15:56 0 -> /dev/pts/1l-wx------ 1 pi pi 64 Aug 23 15:56 1 -> /home/pi/test.outputlrwx------ 1 pi pi 64 Aug 23 15:56 2 -> /dev/pts/1

output을 redirect하면

standard output 이 /home/pi/test.output으로 지정됨.

Page 55: Character Encoding in python

터미널 vs 파일

print 'Standard output encoding is', sys.stdout.encoding

터미널 : Standard output encoding is UTF-8Standard output encoding is EUC-KR

파일 :Standard output encoding is None

Page 56: Character Encoding in python

Python은 file의 Encoding을 알지 못함.

애매하지 않게 정해 주어야 함

Page 57: Character Encoding in python

Solution #1# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8')

Solution #2import sys import codecs sys.stdout = codecs.getwriter('utf8')(sys.stdout)

Page 58: Character Encoding in python

일본어 디코딩 이야기

Page 59: Character Encoding in python

일본시스템 HTTP를 이용한 파일 전송 Python

Java/JDBC

시스템 구조

jpype미지의 세계

Page 60: Character Encoding in python

설명에 따르면...Encoding 을 알려주지 않고.

83년버전 JIS 한자 코드와 76년 버전 JIS 코드 혼재한자 문자열 중에 1byte계 문자가 혼재함(이런 설명이 쭉 이어짐…)

MS 일본에 있는 친구에게 물어봐도 모르겠다고 함.

Page 61: Character Encoding in python

일단 알고 있는 모든 Encoding을 시도print 'Detect :', chardet.detect(readdata)print 'Received data :', readdata, ':'.join(x.encode('hex') for x readdataprintENCODINGS = ['ISO-2022-JP', 'UTF-8', 'EUC-JP', 'SJIS']for ENCODING in ENCODINGS: print ENCODING, codecs.decode( readdata, ENCODING )

Detect : {'confidence': 1.0, 'encoding': 'ascii'} Received data : 5\:j@>#I#C 35:5c:3a:6a:40:3e:23:49:23:43

ISO-2022-JP : 5\:j@>#I#CUTF-8 : 5\:j@>#I#CEUC-JP : 5\:j@>#I#CSJIS : 5\:j@>#I#C

디코딩이 제대로 안되었다.

Page 62: Character Encoding in python

Tip #2 : 인코딩 파악

주고 받을 인코딩을 정확히 파악!

정의된 문서도 보고,주고 받은 내용을 직접 보고,

테스트!

Page 63: Character Encoding in python

인코딩에서 어려움을 가지는 사람들...

“ Encode, Decode 이렇게 저렇게 해보다가, 잘 되면 그것을 써요. ”

망하는 지름길

Page 64: Character Encoding in python

bytes(python2/str)로 입력str(python3/unicode)로 decode

with 정확한 encoding

Page 65: Character Encoding in python

일단 원본 데이터를 보자 print 'Received data :', readdata, ':'.join(x.encode('hex') for x readdata Received data : 5\:j@>#I#C 35:5c:3a:6a:40:3e:23:49:23:43

35 - 0011 0101 5c - 0101 1100 3a - 0011 1010 6a - 0110 1010 40 - 0100 0000

7bit encoding 인가?

Page 67: Character Encoding in python

ISO-2022-JP

ESC $ B 를 추가.

ENCODING = 'ISO-2022-JP'ESCseq = ‘\x1b$B’print ENCODING, codecs.decode( ESCseq + readdata, ENCODING )

결과

ISO-2022-JP 宮崎西IC

성공

Page 68: Character Encoding in python

인코딩 파악을 위한 순서

1. 문서 또는 서로의 약속을 확인

2. 전송 받은 데이터를 열어서 확인 ( 다음장에서 상세 설명 )

3. 테스트

Page 69: Character Encoding in python

인코딩을 확인 & 파악 vi ( :r !xxd filename ) or 16진수 지원 Editor ':'.join(x.encode('hex') for x readdata example) 50 79 43 6F 6E EA B0 95

EB 8C 80 EC 84 B1 UTF-8 느낌

Page 70: Character Encoding in python

인코딩 파악에 도움이 될만한 것

Page 71: Character Encoding in python

UTF-8 : Paris, 3일, EUR 500ISO-8859-15 : München, 2Days, €400EUC-KR : 로마, 4일, 300유로ISO-8859-1 : London, 3D, £300

print chardet.detect(readdata)

{'confidence': 0.938125, 'encoding': 'utf-8'}{'confidence': 0.6450620150892906, 'encoding': 'ISO-8859-2'}{'confidence': 0.99, 'encoding': 'EUC-KR'}{'confidence': 0.7388892172840966, 'encoding': 'ISO-8859-2'}

Page 72: Character Encoding in python

테스트

전체 프로그램으로 테스트 하면 시간이 오래 걸릴 수 있으니, 해당 부분만 따로 떼어서 테스트 해본다.

ENCODING = 'ISO-2022-JP'ESCseq = ‘\x1b$B’print ENCODING, codecs.decode( ESCseq + readdata, ENCODING )

결과

ISO-2022-JP 宮崎西IC

Page 73: Character Encoding in python

Python에서 만든 데이터를다른 프로그램에서 못 읽어요.

Page 74: Character Encoding in python

대학교 때부터 함께 놀던 친구들 모임

단체 대화방에서 어느날 .... “Python에서 생성한 csv가 mac용 excel에서 열리지 않는다.. ”

Page 75: Character Encoding in python

직급은 한글 2자리

ASCII영역문자들은 잘 보임

직급이 6개의 무엇인가로 구성됨.

Page 76: Character Encoding in python

vi :r !xxd result.csv

유추 : UTF-8 Encoding 으로 된 것 같네…

MS Excel for Mac 2011에서 UTF-8 가능?

Page 77: Character Encoding in python

http://stackoverflow.com/questions/6588068/which-encoding-opens-csv-files-correctly-with-excel-on-both-mac-and-windows

이게 가장 좋겠다.UTF-16LE with BOM

Excel for Mac 에 대한 자료를 검색...

Page 78: Character Encoding in python

친구의 소스 (Python2)# -*- coding: utf-8 -*-

f = open(target_path, 'w')f.write("uidx, id, phone, name, 회사, 직장번호, 직급\n")f.close()

Page 79: Character Encoding in python

바꾸어 준 소스 (Python2)# -*- coding: utf-8 -*-

import codecs

f = codecs.open('testfile.txt', encoding='UTF-16LE', mode='w')f.write(u"\ufeff" ) # BOMf.write(u"uidx\t id\t phone\t name\t 회사\t 직장번호\t 직급\n")f.close()

Page 80: Character Encoding in python

결과

‘\ud68c\uc0ac’ (회사)

Page 81: Character Encoding in python

파일 IO를 위한 TIP

파일을 열 때 codecs 쓰면 간단해짐. fp = codecs.open('testfile.txt', encoding='UTF-16LE', ...)

Python3에는 내장함수에서 가능 fp = open( encoding = ‘UTF-8’, ... )

Page 82: Character Encoding in python
Page 83: Character Encoding in python

출력가능한 ASCII는 그대로나머지는 8bit를 “=XX”으로 표시

0xC3BCCP1252 = ü UTF-8 = ü표시하려고 했던 단어 für하지만 für

0xEFBBBF이건 UTF-8 BOM 같은데...

Page 84: Character Encoding in python

정리 : 이것만은 기억하세요.

Tip #1 : Unicode Sandwich Python에선 항상 Unicode

Tip #2 : 인코딩 파악하기 문서보고, 확인하고, 테스트 주어야하는 인코딩도 명확히

Page 85: Character Encoding in python

[email protected]

좋은 개발 문화직원의 성장합당한 보상

Page 86: Character Encoding in python

감사합니다A/S 보장 !!인코딩에 관련된 궁금한 사항이 있다면?스터디/모임에서 Encoding 에 관련된 세미나가 필요하다면?

mailto : [email protected]