Python 의 문자 인코딩

PythonBeginner
지금 연습하기

소개

이 랩에서는 Python 에서의 문자 인코딩에 대한 포괄적인 이해를 얻게 됩니다. ASCII 및 국가별 ANSI 인코딩과 같은 초기 인코딩의 한계부터 Unicode 표준 및 UTF-8 과 같은 다양한 구현의 개발 및 중요성에 이르기까지 문자 인코딩의 역사와 기본 개념을 탐구하는 것으로 시작하겠습니다. Python 환경에서 기본 인코딩을 확인하는 방법을 배우게 됩니다.

이러한 기초를 바탕으로 Python 에서 문자 인코딩을 다루는 실용적인 기술을 배우게 됩니다. 여기에는 ord()chr() 함수를 사용하여 문자와 해당 정수 표현 간에 변환하고, encode()decode() 메서드를 사용하여 문자열과 바이트 간에 변환하는 방법을 익히는 것이 포함됩니다. 마지막으로 디코딩 과정에서 발생할 수 있는 잠재적인 인코딩 오류를 효과적으로 처리하는 방법을 배워 Python 애플리케이션에서 강력하고 안정적인 텍스트 처리를 보장합니다.

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 초급 레벨의 실험이며 완료율은 88%입니다.학습자들로부터 98%의 긍정적인 리뷰율을 받았습니다.

문자 인코딩의 역사와 개념 탐구

이 단계에서는 문자 인코딩의 역사와 기본 개념을 탐구합니다. 컴퓨터가 텍스트를 어떻게 표현하는지 이해하는 것은 다양한 데이터 형식 및 언어를 다루는 데 중요합니다.

초기에 컴퓨터는 미국에서 개발되었으며, 이로 인해 ASCII 인코딩이 만들어졌습니다. ASCII 는 문자를 표현하기 위해 단일 바이트를 사용하며 영어 알파벳, 숫자 및 기호를 포함하여 총 128 개의 문자로 구성됩니다.

컴퓨터가 전 세계적으로 더 널리 보급됨에 따라 ASCII 는 다른 언어의 문자를 표현하기에 불충분하다는 것이 입증되었습니다. 이로 인해 GB2312, GBK, Big5, Shift_JIS 와 같은 다양한 국가별 인코딩이 개발되었습니다. 이들은 종종 통칭하여 ANSI 인코딩이라고 불렸습니다.

이러한 분산된 인코딩의 한계를 해결하기 위해 Unicode 표준이 개발되었습니다. Unicode 는 모든 언어의 모든 문자에 대해 고유한 이진 코드를 제공하여 다양한 플랫폼 및 언어 전반에 걸쳐 일관된 텍스트 처리를 가능하게 하는 것을 목표로 합니다. Unicode 는 문자 코드를 정의하지만 저장 방식은 정의하지 않습니다.

UCS4, UTF-8, UTF-16, UTF-32 를 포함한 여러 인코딩 체계가 Unicode 를 구현합니다. 이들 중에서 UTF-8 은 ASCII 와의 하위 호환성으로 인해 널리 사용됩니다.

Python 3 에서 기본 인코딩은 UTF-8 이며, 이를 통해 악센트가 있는 문자 및 기호를 포함한 다양한 언어의 문자를 직접 사용할 수 있습니다. Python 2 와 같은 이전 버전에서는 일반적으로 ## -*- coding: UTF-8 -*- 또는 ## coding=utf-8과 같은 주석을 사용하여 스크립트 시작 부분에 인코딩을 지정해야 했습니다.

sys 모듈을 사용하여 Python 환경에서 기본 인코딩을 확인할 수 있습니다.

먼저 Terminal -> New Terminal을 클릭하여 WebIDE 의 통합 터미널을 엽니다.

그런 다음 python을 입력하고 Enter 키를 눌러 Python 대화형 인터프리터를 시작합니다.

python

다음과 유사한 출력이 표시됩니다.

Python 3.10.x (main, ...)
[GCC ...] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

이제 sys 모듈을 가져와 기본 인코딩을 확인합니다.

import sys
sys.getdefaultencoding()

출력은 기본 인코딩을 표시하며, Python 3 에서는 일반적으로 utf-8입니다.

>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
>>>

exit()를 입력하고 Enter 키를 눌러 Python 인터프리터를 종료합니다.

exit()

ord() 및 chr() 을 사용하여 문자와 정수 변환하기

이 단계에서는 내장 Python 함수인 ord()chr()을 사용하여 문자와 해당 Unicode 정수 표현 간에 변환하는 방법을 배웁니다.

Python 3 에서는 문자열이 Unicode 를 사용하여 표현됩니다. ord() 함수는 단일 문자를 입력으로 받아 해당 Unicode 십진수 정수 값을 반환합니다.

이 함수들을 실험하기 위해 새로운 Python 파일을 만들어 보겠습니다. WebIDE 에서 파일 탐색기의 project 디렉토리를 마우스 오른쪽 버튼으로 클릭하고 New File을 선택합니다. 파일 이름을 char_conversion.py로 지정합니다.

char_conversion.py를 편집기에서 열고 다음 코드를 추가합니다.

## 문자의 Unicode 십진수 값을 얻기 위해 ord() 사용
char1 = 'a'
char2 = 'é'
char3 = ';'

print(f"'{char1}'의 Unicode 십진수 값은: {ord(char1)}")
print(f"'{char2}'의 Unicode 십진수 값은: {ord(char2)}")
print(f"'{char3}'의 Unicode 십진수 값은: {ord(char3)}")

파일을 저장합니다 (Ctrl + S 또는 macOS 에서는 Cmd + S).

이제 통합 터미널을 다시 열고 (이미 열려 있지 않다면) python 명령을 사용하여 스크립트를 실행합니다.

python char_conversion.py

다음과 유사한 출력이 표시됩니다.

'a'의 Unicode 십진수 값은: 97
'é'의 Unicode 십진수 값은: 233
';'의 Unicode 십진수 값은: 59

chr() 함수는 반대 작업을 수행합니다. Unicode 코드 포인트를 나타내는 십진수 정수 (또는 16 진수 정수) 를 받아 해당 문자를 반환합니다.

chr() 함수를 사용하기 위해 char_conversion.py에 코드를 더 추가해 보겠습니다. 기존 코드에 다음 줄을 추가합니다.

## Unicode 십진수 값에서 문자를 얻기 위해 chr() 사용
int1 = 8364
int2 = 8482

print(f"Unicode 십진수 값 {int1}에 대한 문자는: {chr(int1)}")
print(f"Unicode 십진수 값 {int2}에 대한 문자는: {chr(int2)}")

## chr() 과 함께 16 진수 값도 사용할 수 있습니다.
hex_int = 0x00A9 ## 문자 '©'에 대한 16 진수
print(f"Unicode 16 진수 값 {hex(hex_int)}에 대한 문자는: {chr(hex_int)}")

파일을 다시 저장합니다.

터미널에서 스크립트를 실행합니다.

python char_conversion.py

출력에는 이제 chr() 함수의 결과가 포함됩니다.

'a'의 Unicode 십진수 값은: 97
'é'의 Unicode 십진수 값은: 233
';'의 Unicode 십진수 값은: 59
Unicode 십진수 값 8364에 대한 문자는: €
Unicode 십진수 값 8482에 대한 문자는: ™
Unicode 16진수 값 0xa9에 대한 문자는: ©

문자의 16 진수 Unicode 표현을 찾는 방법을 궁금해할 수 있습니다. ord() 함수를 사용하여 십진수 값을 얻은 다음 내장 hex() 함수를 사용하여 십진수 값을 해당 16 진수 문자열 표현으로 변환할 수 있습니다.

char_conversion.py에 다음 코드를 추가합니다.

## 문자를 16 진수 Unicode 표현으로 변환
char_copyright = '©'
decimal_copyright = ord(char_copyright)
hexadecimal_copyright = hex(decimal_copyright)

print(f"'{char_copyright}'의 16 진수 Unicode 값은: {hexadecimal_copyright}")

파일을 저장하고 마지막으로 한 번 더 실행합니다.

python char_conversion.py

최종 출력에는 문자 '©'에 대한 16 진수 값이 포함됩니다.

'a'의 Unicode 십진수 값은: 97
'é'의 Unicode 십진수 값은: 233
';'의 Unicode 십진수 값은: 59
Unicode 십진수 값 8364에 대한 문자는: €
Unicode 십진수 값 8482에 대한 문자는: ™
Unicode 16진수 값 0xa9에 대한 문자는: ©
'©'의 16진수 Unicode 값은: 0xa9

이를 통해 Python 에서 ord(), chr(), hex()를 함께 사용하여 문자 인코딩을 다루는 방법을 알 수 있습니다.

encode() 및 decode() 를 사용하여 문자열과 바이트 간 변환

이 단계에서는 Python 문자열 (Unicode) 과 바이트 객체 간에 encode()decode() 메서드를 사용하여 변환하는 방법을 배웁니다. 이는 특정 인코딩 형식으로 전송하거나 저장해야 하는 데이터를 다룰 때 필수적입니다.

encode() 메서드는 지정된 인코딩을 사용하여 문자열을 바이트 객체로 변환하는 데 사용됩니다. bytes 객체를 반환합니다.

~/project 디렉토리에 encoding_decoding.py라는 새 Python 파일을 만들어 보겠습니다.

encoding_decoding.py를 편집기에서 열고 다음 코드를 추가합니다.

## 문자열 정의
my_string = 'café'

## UTF-8 을 사용하여 문자열 인코딩
encoded_utf8 = my_string.encode('utf-8')

## Latin-1 을 사용하여 문자열 인코딩
encoded_latin1 = my_string.encode('latin-1')

## 인코딩된 바이트 객체 출력
print(f"원본 문자열: {my_string}")
print(f"UTF-8 으로 인코딩됨: {encoded_utf8}")
print(f"Latin-1 으로 인코딩됨: {encoded_latin1}")

파일을 저장합니다.

이제 통합 터미널에서 스크립트를 실행합니다.

python encoding_decoding.py

원본 문자열과 UTF-8 및 Latin-1 에서의 바이트 표현을 보여주는 출력이 표시됩니다.

원본 문자열: café
UTF-8으로 인코딩됨: b'caf\xc3\xa9'
Latin-1으로 인코딩됨: b'caf\xe9'

바이트 객체에 대한 출력은 b'로 시작하여 바이트 리터럴임을 나타냅니다. 16 진수 숫자는 각 인코딩에서 문자열의 바이트 시퀀스를 나타냅니다.

decode() 메서드는 지정된 인코딩을 사용하여 바이트 객체를 다시 문자열로 변환하는 데 사용됩니다.

생성한 바이트 객체를 디코딩하기 위해 encoding_decoding.py에 코드를 추가해 보겠습니다. 기존 코드에 다음 줄을 추가합니다.

## 바이트 객체를 다시 문자열로 디코딩
decoded_utf8 = encoded_utf8.decode('utf-8')
decoded_latin1 = encoded_latin1.decode('latin-1')

## 디코딩된 문자열 출력
print(f"UTF-8 에서 디코딩됨: {decoded_utf8}")
print(f"Latin-1 에서 디코딩됨: {decoded_latin1}")

파일을 저장합니다.

스크립트를 다시 실행합니다.

python encoding_decoding.py

출력에는 이제 UTF-8 및 Latin-1 바이트에서 성공적으로 디코딩된 원본 문자열이 표시됩니다.

원본 문자열: café
UTF-8으로 인코딩됨: b'caf\xc3\xa9'
Latin-1으로 인코딩됨: b'caf\xe9'
UTF-8에서 디코딩됨: café
Latin-1에서 디코딩됨: café

이는 특정 인코딩을 사용하여 문자열을 바이트로 인코딩하고 바이트를 다시 문자열로 디코딩하는 기본 프로세스를 보여줍니다. 오류를 피하려면 인코딩 및 디코딩 모두에 올바른 인코딩을 사용하는 것이 중요하며, 이는 다음 단계에서 살펴보겠습니다.

디코딩 중 인코딩 오류 처리하기

이 단계에서는 잘못된 인코딩을 사용하여 바이트를 디코딩하려고 할 때 어떤 일이 발생하는지, 그리고 이러한 오류를 어떻게 처리하는지 살펴보겠습니다.

이전 단계에서 보았듯이 바이트를 성공적으로 디코딩하려면 해당 바이트를 생성하는 데 사용된 원본 인코딩을 알아야 합니다. 호환되지 않는 인코딩으로 바이트를 디코딩하려고 하면 Python 에서 오류가 발생합니다.

이를 시연하기 위해 encoding_decoding.py 파일을 수정해 보겠습니다. 파일을 편집기에서 열고 다음 코드를 끝에 추가합니다.

## ASCII 를 사용하여 Latin-1 으로 인코딩된 바이트 디코딩 시도
try:
    decoded_incorrectly = encoded_latin1.decode('ascii')
    print(f"ASCII 를 사용하여 Latin-1 에서 디코딩됨: {decoded_incorrectly}")
except UnicodeDecodeError as e:
    print(f"ASCII 로 Latin-1 디코딩 중 오류 발생: {e}")

파일을 저장합니다.

터미널에서 스크립트를 실행합니다.

python encoding_decoding.py

출력에는 이제 ASCII 로 Latin-1 바이트를 디코딩하려고 할 때 오류 메시지가 포함됩니다.

원본 문자열: café
UTF-8으로 인코딩됨: b'caf\xc3\xa9'
Latin-1으로 인코딩됨: b'caf\xe9'
UTF-8에서 디코딩됨: café
Latin-1에서 디코딩됨: café
ASCII로 Latin-1 디코딩 중 오류 발생: 'ascii' codec can't decode byte 0xe9 in position 3: ordinal not in range(128)

UnicodeDecodeError는 ASCII 코덱이 ASCII 표준에 따라 유효하지 않은 바이트를 만났음을 나타냅니다. 이 경우 바이트 0xe9는 'é'의 Latin-1 표현이지만 유효한 ASCII 문자가 아닙니다 (ASCII 는 0-127 범위의 문자만 포함합니다).

디코딩할 때 decode() 메서드의 errors 매개변수를 사용하여 오류를 처리하는 방법을 지정할 수도 있습니다. 일반적인 오류 처리 전략은 다음과 같습니다.

  • 'strict' (기본값): UnicodeDecodeError를 발생시킵니다.
  • 'ignore': 디코딩할 수 없는 바이트를 무시합니다.
  • 'replace': 디코딩할 수 없는 바이트를 대체 문자 (일반적으로 ``) 로 바꿉니다.
  • 'xmlcharrefreplace': 디코딩할 수 없는 바이트를 XML 문자 참조로 바꿉니다.

encoding_decoding.py'ignore''replace' 오류 처리 전략을 사용하는 예제를 추가해 보겠습니다. 다음 코드를 추가합니다.

## 오류 처리와 함께 ASCII 를 사용하여 Latin-1 으로 인코딩된 바이트 디코딩 시도
decoded_ignore = encoded_latin1.decode('ascii', errors='ignore')
decoded_replace = encoded_latin1.decode('ascii', errors='replace')

print(f"ASCII 를 사용하여 Latin-1 에서 디코딩됨 (오류 무시): {decoded_ignore}")
print(f"ASCII 를 사용하여 Latin-1 에서 디코딩됨 (오류 대체): {decoded_replace}")

파일을 저장합니다.

스크립트를 다시 실행합니다.

python encoding_decoding.py

출력에는 이제 오류 처리 결과가 표시됩니다.

원본 문자열: café
UTF-8으로 인코딩됨: b'caf\xc3\xa9'
Latin-1으로 인코딩됨: b'caf\xe9'
UTF-8에서 디코딩됨: café
Latin-1에서 디코딩됨: café
ASCII로 Latin-1 디코딩 중 오류 발생: 'ascii' codec can't decode byte 0xe9 in position 3: ordinal not in range(128)
ASCII를 사용하여 Latin-1에서 디코딩됨 (오류 무시): caf
ASCII를 사용하여 Latin-1에서 디코딩됨 (오류 대체): caf

보시다시피, 'ignore'는 잘못된 바이트가 무시되어 'é' 문자가 제거되었기 때문에 "caf"가 됩니다. 'replace'는 잘못된 바이트를 대체 문자 ``로 바꾸어 "caf"가 됩니다.

적절한 오류 처리 전략을 선택하는 것은 특정 요구 사항에 따라 다릅니다. 대부분의 경우 개발 중에 'strict'를 사용하여 인코딩 문제를 조기에 발견하는 것이 가장 좋습니다. 프로덕션에서는 인코딩 문제가 있는 데이터를 처리해야 하는 경우 'replace' 또는 'ignore'를 선택할 수 있지만, 이로 인해 데이터 손실이나 손상이 발생할 수 있음을 인지해야 합니다.

요약

이 실습에서는 ASCII 와 그 한계에서 시작하여 다양한 국가별 인코딩의 개발로 이어지고 궁극적으로 유니코드 표준으로 이어진 문자 인코딩의 역사와 기본 개념을 탐구했습니다. 우리는 유니코드가 모든 문자에 고유한 코드를 제공하며 Python 3 의 기본값이고 ASCII 와 하위 호환되는 UTF-8 과 같은 다양한 인코딩 스킴으로 구현된다는 것을 배웠습니다. 또한 sys 모듈을 사용하여 Python 에서 기본 인코딩을 확인하는 방법을 배웠습니다.

그런 다음 ord()chr() 함수를 사용하여 문자와 해당 정수 표현 간에, 그리고 encode()decode() 메서드를 사용하여 문자열과 바이트 간에 변환하는 연습을 했습니다. 마지막으로 디코딩 과정에서 발생할 수 있는 잠재적인 인코딩 오류를 처리하는 방법을 다루었습니다.