[python] python3 힘들게 배우기 #7

9 분 소요

ex22. 복습

간단한 복습에 대한 내용이다. ex1~ex21까지의 내용을 복습해 보자.

ex23. String, Bytes, Character Encodings

상당히 어려운 수준의 예제가 처음으로 등장한다. 이번 예제는 반드시 전부 이해하고 갈 필요 없을 정도로 어렵다. 이번 예제에서는 다음과 같은 개념에 대해 배우는데..

  1. 현대 컴퓨터들이 사람의 언어를 어떻게 display하고 처리하는지와 python3이 어떻게 string을 부르는지?
  2. 어떻게 Python의 string을 bytes를 이용하여 “encode” 및 “decode”하는지?
  3. 어떻게 byte handling 의 에러를 처리하는지?
  4. 어떻게 코드를 읽고 지금까지 보지 못했던 것을 찾는지?

이번에는 함수들을 먼저 짚고 넘어가도록 하자.

  • str.strip([chars])

여기의 내용을 참고했다. (왠만한 기본적인 것은 공식 사이트를 이용하는것이 설명이 훨씬 좋더라..specific한 질문은 stackoverflow가 좋지만)strip에서 알 수 있듯이, 문자의 앞 뒤를 잘러버린다. [chars]로 이루어진 모든 조합 에 대해서 생략을 해준다. [chars]가 omit될 경우 공백을 없애준다. 아래 예시를 살펴보자.

'   I AM A BOY   '.strip() # >>> 'I AM A BOY'
'@$ I AM A BOY@$ $'.strip('@$ ') # >>> 'I AM A BOY'
  • str.encode(encoding="utf-8", errors="strict")

여기를 참고했다. str을 원하는 형식으로 인코딩 해주는 것.

  • bytes.decode(encoding="utf-8", errors="strict")

여기의 내용을 참고하도록 하자. byte로 되어있는 것을 디코딩하여 인간의 언어로 번역해 준다.

그럼 인코딩과 디코딩이란 무엇일까? 컴퓨터의 문자들이 나타내어지는 원리는 아주 간단하다고 볼 수 있다. 0과 1의 조합을 각각의 언어에 1:1 매칭시켜서 나타내어준것에 불과하다. 그리고 이런 0과 1들은 ‘bit’라고 불리운다. 예를 들면 8자리 2진법숫자를 이용한다고 가정했을 때 우리는 2의 8승인 256개의 경우의 수를 가질 수 있다. (00000000 ~ 11111111, 십진수로 하면 0 ~ 255) 결국 “encode”가 의미하는 바는 무엇인가? 어떤 숫자가 어떤 인간의 언어를 나타내는지 약속한 것에 불과한 것이다.

오늘날에는 우리는 8bit(8자리 2진수)를 1byte라고 부르고 있다. 아무튼, 컴퓨터 발전사 초기에는 이 약속에도 굉장히 여러 가지 버전이 있었고 사람들이 각자 쓰는 방식이 달랐지만 결국에는 우리가 흔히 ASCII라고 부르는 숫자-알파벳 매칭 방식(American Standard Code for Information Interchange)이 남게 된다. 예시를 같이 보도록 하자. 숫자 90은 알파벳 Z에 해당하고 bit에 해당하는 것은 1011010 이다. 즉 모든 알파벳은 0~256개의 차고 넘치는 숫자들에 1:1로 대응시킬 수 있게 되는데, 이 말은 어떤 알파벳(+@)을 쓰는 데 컴퓨터가 먹는 용량은 8bit(1byte)면 충분하다는 것이다. KIM이라는 단어를 표현하는데는? 3byte면 충분하다.

문제는 ASCII는 단순히 영어와 그 비슷한 알파벳을 가진 언어에만 국한되어 사용될 수 있는 방식이고, 0~255 즉 256개의 조합을 이용해서는 충분하겠지만 전 세계의 다양한 언어방식을 사용하는데는 충분치 않다는 점이다.

이 문제를 해결하기 위해서 만들어진 것이 바로 유니코드(Unicode)다. universal encoding이라는 뜻으로서 모든 인간 언어를 이용하기 위해 만들어졌다. 32bit의 큰 용량으로서 이것만 있으면 2^32승의 어마무시한 문자를 표현할 수 있는 가짓수를 가지게 된다.

하지만 이는 또 굉장한 용량 낭비를 초래할 수 있기 떄문에, 한 걸음 더 나아간 것이 바로 utf-8 방식이며 이는 Unicode Transformation Format for 8 bit의 약자이다. 의미는 8bit의 인코딩 체계를 이용하되 필요한 경우에만 unicode를 이용하는 방법을 사용함으로서 낭비되는 용량을 줄이는 방법이다. 이것이 Python에서 이용하는 인코딩 방식이다.

자.. 그렇다면 한번 코딩으로 들어가 보자. 먼저 여기 서 세계 각국의 언어가 ‘utf-8’을 이용하여(인코딩방식) 작성되어 있는 파일을 하나 다운받자.

아래와 같은 코드를 작성하자.


# import argv from sys와 동일한 과정
import sys

script, encoding_type, error_type = sys.argv

# line 변수에 언어를 하나씩 넣어줌. 재귀함수임에 주목
def main(file, encoding_type, error_type):
    line = file.readline()

    if line:
        print_line(line, encoding_type, error_type)
        main(file, encoding_type, error_type)

#각 언어를 한번은 인코딩 하고 다시 그것을 디코딩하여 각각 프린트한다.
def print_line(text_line, encoding, error_type):
    next_lang = text_line.strip()
    raw_bytes = next_lang.encode(encoding, errors = error_type)
    cooked_string = raw_bytes.decode(encoding, errors = error_type)

    print(raw_bytes, " <====> ", cooked_string)

#파일 open
language = open("language.txt", encoding = "utf-8")

#메인함수 시작
main(language, encoding_type, error_type)

지금까지 수행했던 것에 비하면 상당히 복잡한 코드이다. 파워셀을 키고 python ex23.py utf-8 strict로 실행해보자. 물론 languages.txt파일은 ex23.py와 같은 폴더에 있어야겠죠?

먼저 main함수를 통해 각 언어를 하나씩 line변수에 집어넣는 일을 하고, line에 값이 있을 경우(즉 true일 경우) if 문 이하를 실행하도록 만들어 놨다. if문에는 print_line함수와 함께 다시 main함수를 넣어놨는데.. 재귀함수의 개념을 이렇게 바로 넣다니!

하여튼, print_line함수는 다른게 아니고 그냥 인코딩과 디코딩 한 것을 한번씩 보여주는 함수이다. 즉 string은 인코딩하면 raw bytes형태가 되는 거고, raw bytes 는 디코딩하면 string이 되는 것 이다.

raw bytes의 형태라는 것을 알 수 있는 것이 바로 b' ' 이며 파이썬으로 하여금 b안에 있는 것이 raw byte라는 것이라고 말해주는 것과 같다.

위 사항을 수행하면

b'Afrikaans'  <====>  Afrikaans
b'\xe1\x8a\xa0\xe1\x88\x9b\xe1\x88\xad\xe1\x8a\x9b'  <====>  አማርኛ
b'\xd0\x90\xd2\xa7\xd1\x81\xd1\x88\xd3\x99\xd0\xb0'  <====>  Аҧсшәа
b'\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9'  <====>  العربية
b'Aragon\xc3\xa9s'  <====>  Aragonés
b'Arpetan'  <====>  Arpetan
b'Az\xc9\x99rbaycanca'  <====>  Azərbaycanca
b'Bamanankan'  <====>  Bamanankan
b'\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe'  <====>  বাংলা
b'B\xc3\xa2n-l\xc3\xa2m-g\xc3\xba'  <====>  Bân-lâm-gú
b'\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd0\xba\xd0\xb0\xd1\x8f'  <====>  Беларуская
b'\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8'  <====>  Български
b'Boarisch'  <====>  Boarisch
b'Bosanski'  <====>  Bosanski
b'\xd0\x91\xd1\x83\xd1\x80\xd1\x8f\xd0\xb0\xd0\xb4'  <====>  Буряад
b'Catal\xc3\xa0'  <====>  Català
b'\xd0\xa7\xd3\x91\xd0\xb2\xd0\xb0\xd1\x88\xd0\xbb\xd0\xb0'  <====>  Чӑвашла
b'\xc4\x8ce\xc5\xa1tina'  <====>  Čeština
b'Cymraeg'  <====>  Cymraeg
b'Dansk'  <====>  Dansk
b'Deutsch'  <====>  Deutsch
b'Eesti'  <====>  Eesti
b'\xce\x95\xce\xbb\xce\xbb\xce\xb7\xce\xbd\xce\xb9\xce\xba\xce\xac'  <====>  Ελληνικά
b'Espa\xc3\xb1ol'  <====>  Español
b'Esperanto'  <====>  Esperanto
b'\xd9\x81\xd8\xa7\xd8\xb1\xd8\xb3\xdb\x8c'  <====>  فارسی
b'Fran\xc3\xa7ais'  <====>  Français
b'Frysk'  <====>  Frysk
b'Gaelg'  <====>  Gaelg
b'G\xc3\xa0idhlig'  <====>  Gàidhlig
b'Galego'  <====>  Galego
b'\xed\x95\x9c\xea\xb5\xad\xec\x96\xb4'  <====>  한국어
b'\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa5\xd6\x80\xd5\xa5\xd5\xb6'  <====>  Հայերեն
b'\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\xa8\xe0\xa5\x8d\xe0\xa4\xa6\xe0\xa5\x80'  <====>  हिन्दी
b'Hrvatski'  <====>  Hrvatski
b'Ido'  <====>  Ido
b'Interlingua'  <====>  Interlingua
b'Italiano'  <====>  Italiano
b'\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa'  <====>  עברית
b'\xe0\xb2\x95\xe0\xb2\xa8\xe0\xb3\x8d\xe0\xb2\xa8\xe0\xb2\xa1'  <====>  ಕನ್ನಡ
b'Kapampangan'  <====>  Kapampangan
b'\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\xa3\xe1\x83\x9a\xe1\x83\x98'  <====>  ქართული
b'\xd2\x9a\xd0\xb0\xd0\xb7\xd0\xb0\xd2\x9b\xd1\x88\xd0\xb0'  <====>  Қазақша
b'Krey\xc3\xb2l ayisyen'  <====>  Kreyòl ayisyen
b'Latga\xc4\xbcu'  <====>  Latgaļu
b'Latina'  <====>  Latina
b'Latvie\xc5\xa1u'  <====>  Latviešu
b'L\xc3\xabtzebuergesch'  <====>  Lëtzebuergesch
b'Lietuvi\xc5\xb3'  <====>  Lietuvių
b'Magyar'  <====>  Magyar
b'\xd0\x9c\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8'  <====>  Македонски
b'Malti'  <====>  Malti
b'\xe0\xa4\xae\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xa0\xe0\xa5\x80'  <====>  मराठी
b'\xe1\x83\x9b\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x92\xe1\x83\x90\xe1\x83\x9a\xe1\x83\xa3\xe1\x83\xa0\xe1\x83\x98'  <====>  მარგალური
b'\xd9\x85\xd8\xa7\xd8\xb2\xd9\x90\xd8\xb1\xd9\x88\xd9\x86\xdb\x8c'  <====>  مازِرونی
b'Bahasa Melayu'  <====>  Bahasa Melayu
b'\xd0\x9c\xd0\xbe\xd0\xbd\xd0\xb3\xd0\xbe\xd0\xbb'  <====>  Монгол
b'Nederlands'  <====>  Nederlands
b'\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa4\xbe\xe0\xa4\xb2 \xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb7\xe0\xa4\xbe'  <====>  नेपाल भाषा
b'\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e'  <====>  日本語
b'Norsk bokm\xc3\xa5l'  <====>  Norsk bokmål
b'Nouormand'  <====>  Nouormand
b'Occitan'  <====>  Occitan
b'O\xca\xbbzbekcha/\xd1\x9e\xd0\xb7\xd0\xb1\xd0\xb5\xd0\xba\xd1\x87\xd0\xb0'  <====>  Oʻzbekcha/ўзбекча
b'\xe0\xa8\xaa\xe0\xa9\xb0\xe0\xa8\x9c\xe0\xa8\xbe\xe0\xa8\xac\xe0\xa9\x80'  <====>  ਪੰਜਾਬੀ
b'\xd9\xbe\xd9\x86\xd8\xac\xd8\xa7\xd8\xa8\xdb\x8c'  <====>  پنجابی
b'\xd9\xbe\xda\x9a\xd8\xaa\xd9\x88'  <====>  پښتو
b'Plattd\xc3\xbc\xc3\xbctsch'  <====>  Plattdüütsch
b'Polski'  <====>  Polski
b'Portugu\xc3\xaas'  <====>  Português
b'Rom\xc3\xa2n\xc4\x83'  <====>  Română
b'Romani'  <====>  Romani
b'\xd0\xa0\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9'  <====>  Русский
b'Seeltersk'  <====>  Seeltersk
b'Shqip'  <====>  Shqip
b'Simple English'  <====>  Simple English
b'Sloven\xc4\x8dina'  <====>  Slovenčina
b'\xda\xa9\xd9\x88\xd8\xb1\xd8\xaf\xdb\x8c\xdb\x8c \xd9\x86\xd8\xa7\xd9\x88\xdb\x95\xd9\x86\xd8\xaf\xdb\x8c'  <====>  کوردیی ناوەندی
b'\xd0\xa1\xd1\x80\xd0\xbf\xd1\x81\xd0\xba\xd0\xb8 / srpski'  <====>  Српски / srpski
b'Suomi'  <====>  Suomi
b'Svenska'  <====>  Svenska
b'Tagalog'  <====>  Tagalog
b'\xe0\xae\xa4\xe0\xae\xae\xe0\xae\xbf\xe0\xae\xb4\xe0\xaf\x8d'  <====>  தமிழ்
b'\xe0\xb8\xa0\xe0\xb8\xb2\xe0\xb8\xa9\xe0\xb8\xb2\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2'  <====>  ภาษาไทย
b'Taqbaylit'  <====>  Taqbaylit
b'\xd0\xa2\xd0\xb0\xd1\x82\xd0\xb0\xd1\x80\xd1\x87\xd0\xb0/tatar\xc3\xa7a'  <====>  Татарча/tatarça
b'\xe0\xb0\xa4\xe0\xb1\x86\xe0\xb0\xb2\xe0\xb1\x81\xe0\xb0\x97\xe0\xb1\x81'  <====>  తెలుగు
b'\xd0\xa2\xd0\xbe\xd2\xb7\xd0\xb8\xd0\xba\xd3\xa3'  <====>  Тоҷикӣ
b'T\xc3\xbcrk\xc3\xa7e'  <====>  Türkçe
b'\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb0'  <====>  Українська
b'\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x88'  <====>  اردو
b'Ti\xe1\xba\xbfng Vi\xe1\xbb\x87t'  <====>  Tiếng Việt
b'V\xc3\xb5ro'  <====>  Võro
b'\xe6\x96\x87\xe8\xa8\x80'  <====>  文言
b'\xe5\x90\xb4\xe8\xaf\xad'  <====>  吴语
b'\xd7\x99\xd7\x99\xd6\xb4\xd7\x93\xd7\x99\xd7\xa9'  <====>  ייִדיש
b'\xe4\xb8\xad\xe6\x96\x87'  <====>  中文

이렇게 보이게 된다. powershell은 utf-8을 지원하지 않아서 깨져 보인다. 마찬가지로 브라우져에서도 몇몇 언어가 꺠져보일 것이다. utf-8을 지원하는 텍스트 에디터에서는 언어가 제대로 보이게 된다.

댓글남기기