웹사이트 검색

파이썬에서 유니코드로 작업하는 방법


저자는 Write for DOnations 프로그램을 선택했습니다.

소개

유니코드는 전 세계 대부분의 컴퓨터에서 사용되는 표준 문자 인코딩입니다. 사용 중인 운영 체제나 소프트웨어에 관계없이 문자, 기호, 이모티콘, 심지어 제어 문자까지 포함하는 텍스트가 다양한 장치, 플랫폼 및 디지털 문서에서 동일하게 표시되도록 합니다. 그것은 인터넷과 컴퓨팅 산업의 중요한 부분이며, 그것 없이는 인터넷이 훨씬 더 혼란스럽고 사용하기 어려울 것입니다.

유니코드 자체는 인코딩이 아니지만 지구상의 거의 모든 가능한 문자의 데이터베이스와 비슷합니다. 유니코드에는 데이터베이스의 각 문자에 대한 식별자인 코드 포인트가 포함되어 있으며 0에서 110만 사이의 값을 가질 수 있습니다. 유니코드의 모든 코드 포인트는 U+n으로 표시됩니다. 여기서 U+는 유니코드 코드 포인트임을 나타내고 n은 4개의 집합입니다. 문자의 6자리 16진수로. 128자만 나타내는 ASCII보다 훨씬 강력한 인코딩 시스템입니다. 전 세계 디지털 텍스트를 ASCII로 교환하는 것은 미국식 영어를 기반으로 하고 악센트 문자를 지원하지 않기 때문에 어려웠습니다. 반면에 유니코드에는 거의 150,000개의 문자가 있으며 지구상의 모든 언어에 대한 문자를 포함합니다.

이와 함께 텍스트를 적절하게 처리하고 소프트웨어가 국제화를 달성할 수 있도록 Python과 같은 프로그래밍 언어에 대한 요구 사항이 있습니다. Python은 이메일에서 서버, 웹에 이르기까지 다양한 용도로 사용할 수 있으며 문자열에 유니코드 표준을 채택하여 유니코드를 우아하게 처리합니다.

그러나 Python에서 유니코드로 작업하면 혼란스럽고 오류가 발생할 수 있습니다. 이 자습서에서는 이러한 문제를 방지하는 데 도움이 되도록 Python에서 유니코드를 사용하는 방법에 대한 기본 사항을 제공합니다. Python을 사용하여 유니코드를 해석하고, Python의 정규화 기능으로 데이터를 정규화하고, Python 유니코드 오류를 처리합니다.

전제 조건

이 자습서를 따르려면 다음이 필요합니다.

  • Python이 로컬 또는 원격 서버에 설치되었습니다. Python을 아직 설정하지 않은 경우 자습서 Python 3 설치 및 프로그래밍 환경 설정 방법에 따라 설정할 수 있습니다. Linux 배포판에 적합한 버전을 선택하세요.
  • 기본 Python 프로그래밍 및 Python의 문자열 메서드에 대한 친숙함
  • Python 대화형 콘솔로 작업하는 방법에 대한 지식

1단계 — Python에서 유니코드 코드 포인트 변환

인코딩은 데이터를 컴퓨터에서 읽을 수 있는 형식으로 표현하는 프로세스입니다. ASCII, Latin-1 등 데이터를 인코딩하는 방법에는 여러 가지가 있으며 각 인코딩에는 고유한 장단점이 있지만 가장 일반적인 방법은 UTF-8입니다. 전 세계의 문자를 하나의 문자 집합으로 표현할 수 있는 인코딩 유형입니다. 따라서 UTF-8은 국제화된 데이터로 작업하는 모든 사람에게 필수적인 도구입니다. 일반적으로 UTF-8은 대부분의 목적에 적합합니다. 비교적 효율적이며 다양한 소프트웨어와 함께 사용할 수 있습니다. UTF-8은 유니코드 코드 포인트를 컴퓨터가 이해할 수 있는 16진수 바이트로 변환합니다. 즉, 유니코드가 매핑이고 UTF-8을 사용하면 컴퓨터가 해당 매핑을 이해할 수 있습니다.

Python 3에서 기본 문자열 인코딩은 UTF-8입니다. 즉, Python 문자열의 모든 유니코드 코드 포인트가 자동으로 해당 문자로 변환됩니다.

이 단계에서는 Python의 유니코드 코드 포인트를 사용하여 저작권 기호(©)를 만듭니다. 먼저 터미널에서 Python 대화형 콘솔을 시작하고 다음을 입력합니다.

>>> s =  '\u00A9'
>>> s

이전 코드에서 유니코드 코드 포인트 \u00A9로 문자열 s를 만들었습니다. 앞에서 언급했듯이 Python 문자열은 기본적으로 UTF-8 인코딩을 사용하므로 s 값을 인쇄하면 자동으로 해당 유니코드 기호로 변경됩니다. 코드 포인트 시작 부분에 \\u가 필요합니다. 이것이 없으면 Python은 코드 포인트를 변환할 수 없습니다. 이전 코드의 출력은 해당 유니코드 기호를 반환합니다.

Output
'©'

Python 프로그래밍 언어는 문자열 인코딩 및 디코딩을 위한 내장 함수를 제공합니다. encode() 함수는 문자열을 바이트 문자열로 변환합니다.

이를 시연하려면 Python 대화형 콘솔을 열고 다음 코드를 입력하십시오.

>>> '🅥'.encode('utf-8')

그러면 문자의 바이트 문자열이 출력으로 생성됩니다.

Output
b'\xf0\x9f\x85\xa5'

각 바이트 앞에는 16진수임을 나타내는 \x가 있습니다.

참고: 특수 유니코드 문자를 입력하는 방법은 Windows와 Mac에서 다릅니다. 이전 코드와 기호를 사용하는 이 자습서의 모든 코드에서 Windows의 문자표 유틸리티를 사용하여 기호를 삽입할 수 있습니다. Mac에는 이 기능이 없으므로 가장 좋은 방법은 코드 예제에서 문자를 복사하는 것입니다.

다음으로 decode() 함수를 사용하여 바이트 문자열을 다시 문자열로 변환합니다. decode() 함수는 인코딩 유형을 인수로 받아들입니다. decode() 함수는 문자열 시작 부분에 b 문자를 사용하여 지정된 바이트 문자열만 디코딩할 수 있다는 점도 언급할 가치가 있습니다. b를 제거하면 AttributeError가 발생합니다.

콘솔에 다음을 입력합니다.

>>> b'\xf0\x9f\x85\xa5'.decode('utf-8')

코드는 다음과 같은 출력을 반환합니다.

Output
'🅥'

이제 Python의 유니코드 해석에 대한 근본적인 이해가 생겼습니다. 다음으로 Python의 내장 unicodedata 모듈을 자세히 살펴보고 문자열에서 고급 유니코드 기술을 수행합니다.

2단계 — Python에서 유니코드 정규화

이 단계에서는 Python에서 유니코드를 정규화합니다. 정규화는 서로 다른 글꼴로 작성된 두 문자가 동일한지 여부를 확인하는 데 도움이 되며, 이는 서로 다른 코드 포인트를 가진 두 문자가 동일한 결과를 생성할 때 유용합니다. 예를 들어 유니코드 문자 R는 둘 다 문자 R이므로 사람의 눈에는 동일하지만 컴퓨터는 서로 다른 캐릭터가 됩니다.

다음 코드 예제에서는 이를 자세히 보여 줍니다. Python 콘솔을 열고 다음을 입력합니다.

>>> styled_R = 'ℜ'
>>> normal_R = 'R'
>>> styled_R == normal_R

다음과 같은 결과가 표시됩니다.

Output
False

이 코드는 False를 출력으로 인쇄합니다. Python 문자열은 두 문자가 동일하다고 간주하지 않기 때문입니다. 이러한 구별 능력은 유니코드로 작업할 때 정규화가 중요한 이유입니다.

유니코드에서 일부 문자는 두 개 이상의 문자를 하나로 결합하여 만들어집니다. 정규화는 문자열을 서로 일관되게 유지하기 때문에 이 경우에 중요합니다. 이를 더 잘 이해하려면 Python 콘솔을 열고 다음 코드를 입력하십시오.

>>> s1 =  'hôtel'
>>> s2 = 'ho\u0302tel'
>>> len(s1), len(s2)

앞의 코드에서 ô 문자를 포함하는 문자열 s1을 생성했으며 두 번째 줄에서 문자열 s2는 다음의 코드 포인트를 포함합니다. 곡절 부호( ̂ ). 실행 후 코드는 다음 출력을 반환합니다.

Output
(5, 6)

앞의 출력은 두 문자열이 동일한 문자로 구성되어 있지만 길이가 다르기 때문에 동등하지 않다는 것을 보여줍니다. 동일한 콘솔에 다음을 입력하여 테스트합니다.

>>> s1 == s2

이 코드는 다음 출력을 반환합니다.

Output
False

문자열 변수 s1s2는 동일한 유니코드 문자를 생성하지만 길이가 다르므로 동일하지 않습니다.

normalize() 함수를 사용하여 이 문제를 해결할 수 있으며, 이는 다음 단계에서 수행할 작업입니다.

3단계 — NFD, NFC, NFKD 및 NFKC로 유니코드 정규화

이 단계에서는 문자 조회 및 정규화 기능을 제공하는 unicodedata 모듈의 Python unicodedata 라이브러리에 있는 normalize() 함수를 사용하여 유니코드 문자열을 정규화합니다. normalize() 함수는 정규화 형식을 첫 번째 인수로 사용하고 정규화되는 문자열을 두 번째 인수로 사용할 수 있습니다. 유니코드에는 NFD, NFC, NFKD 및 NFKC의 네 가지 유형의 정규화 형식이 있습니다.

NFD 정규화 형식은 문자를 여러 결합 문자로 분해합니다. 텍스트를 악센트를 구분하지 않게 만들어 검색 및 정렬에 유용할 수 있습니다. 문자열을 바이트로 인코딩하여 이를 수행할 수 있습니다.

콘솔을 열고 다음을 입력하십시오.

>>> from unicodedata import normalize
>>> s1 =  'hôtel'
>>> s2 = 'ho\u0302tel'
>>> s1_nfd = normalize('NFD', s1)
>>> len(s1), len(s1_nfd)

이 코드는 다음 출력을 생성합니다.

Output
(5, 6)

예제에서 알 수 있듯이 문자열 s1을 정규화하면 길이가 한 문자씩 늘어납니다. 이는 ô 기호가 oˆ의 두 문자로 분할되기 때문입니다. 다음 코드를 사용하여 확인할 수 있습니다.

>>> s1.encode(), s1_nfd.encode()

결과 출력은 정규화된 문자열을 인코딩한 후 o 문자가 문자열 s1_nfdˆ 문자에서 분리되었음을 보여줍니다.

Output
(b'h\xc3\xb4tel', b'ho\xcc\x82tel')

NFC 정규화 형식은 먼저 문자를 분해한 다음 사용 가능한 조합 문자로 다시 구성합니다. NFC는 가장 짧은 출력을 생성하기 위해 문자열을 구성하므로 W3C는 웹에서 NFC를 사용할 것을 권장합니다. 키보드 입력은 기본적으로 구성된 문자열을 반환하므로 이 경우 NFC를 사용하는 것이 좋습니다.

예를 들어 대화형 콘솔에 다음을 입력합니다.

>>> from unicodedata import normalize
>>> s2_nfc = normalize('NFC', s2)
>>> len(s2), len(s2_nfc)

이 코드는 다음 출력을 생성합니다.

Output
(6, 5)

예제에서 문자열 s2를 정규화하면 길이가 1씩 줄어듭니다. 대화형 콘솔에서 다음 코드를 실행하여 이를 확인할 수 있습니다.

>>> s2.encode(), s2_nfc.encode()

코드의 출력은 다음과 같습니다.

Output
(b'ho\xcc\x82tel', b'h\xc3\xb4tel')

출력은 oˆ 문자가 단일 ô 문자로 병합되었음을 보여줍니다.

NFKD 및 NFKC 정규화 형식은 "엄격한\ 정규화에 사용되며 유니코드 문자열의 검색 및 패턴 일치와 관련된 다양한 문제에 사용할 수 있습니다. NFKD 및 NFKC의 "K\는 호환성을 나타냅니다.

NFD 및 NFC 정규화 형식은 문자를 분해하지만 NFKD 및 NFKC는 유사하지는 않지만 동등한 문자에 대해 호환성 분해를 수행하여 서식 구분을 제거합니다. 예를 들어 문자열 ②①21과 유사하지 않지만 둘 다 동일한 값을 나타냅니다. NFKC 및 NFKD 정규화 형식은 문자에서 이 서식(이 경우 숫자 주위의 원)을 제거하여 문자의 가장 간략한 형식을 제공합니다.

다음 예는 NFD와 NFKD 정규화 형식 간의 차이점을 보여줍니다. Python 대화형 콘솔을 열고 다음을 입력합니다.

>>> s1 = '2⁵ô'
>>> from unicodedata import normalize
>>> normalize('NFD', s1), normalize('NFKD', s1)

다음과 같은 결과가 표시됩니다.

Output
('2⁵ô', '25ô')

출력은 NFD 형식이 문자열 s1에서 지수 문자를 분해할 수 없지만 NFKD가 지수 형식을 스트라이프하고 호환성 문자(이 경우 지수 5)를 대체했음을 보여줍니다. 이에 상응하는 값(숫자로 5). NFD 및 NFKD 정규화 형식은 여전히 문자를 분해하고 있으므로 이전 NFD 예제에서 본 것처럼 ô 문자의 길이가 1씩 증가해야 합니다. 다음 코드를 실행하여 이를 확인할 수 있습니다.

>>> len(normalize('NFD', s1)), len(normalize('NFKD', s1))

코드는 다음을 반환합니다.

Output
(4, 4)

NFKC 정규화 형식은 비슷한 방식으로 작동하지만 문자를 분해하지 않고 합성합니다. 동일한 Python 콘솔에서 다음을 입력합니다.

>>> normalize('NFC', s1), normalize('NFKC', s1)

코드는 다음을 반환합니다.

Output
('2⁵ô', '25ô')

NFKC는 컴포지션 접근 방식을 따르기 때문에 ô 문자에 대한 문자열이 분해의 경우 1씩 늘어나는 대신 1씩 짧아질 것으로 예상해야 합니다. 다음 코드 줄을 실행하여 이를 확인할 수 있습니다.

>>> len(normalize('NFC', s1)), len(normalize('NFKC', s1))

그러면 다음 출력이 반환됩니다.

Output
(3, 3)

이전 단계를 수행하면 정규화 형식의 유형과 그 차이점에 대한 작업 지식을 갖게 됩니다. 다음 단계에서는 Python의 유니코드 오류를 해결합니다.

4단계 — Python에서 유니코드 오류 해결

Python에서 유니코드를 처리할 때 UnicodeEncodeError 및 UnicodeDecodeError의 두 가지 유형의 유니코드 오류가 발생할 수 있습니다. 이러한 유니코드 오류는 혼란스러울 수 있지만 관리할 수 있으며 이 단계에서 이러한 오류를 모두 수정합니다.

UnicodeEncodeError 해결

유니코드 인코딩은 특정 인코딩을 사용하여 유니코드 문자열을 바이트로 변환하는 프로세스입니다. UnicodeEncodeError는 지정된 인코딩으로 표현할 수 없는 문자가 포함된 문자열을 인코딩하려고 할 때 발생합니다.

이 오류를 생성하려면 ASCII 문자 세트의 일부가 아닌 문자가 포함된 문자열을 인코딩합니다.

콘솔을 열고 다음을 입력하십시오.

>>> ascii_supported = '\u0041'
>>> ascii_supported.encode('ascii')

다음은 출력입니다.

Output
b'A'

그런 다음 다음을 입력합니다.

>>> ascii_unsupported = '\ufb06'
>>> ascii_unsupported.encode('utf-8')

다음과 같은 결과가 표시됩니다.

Output
b'\xef\xac\x86'

마지막으로 다음을 입력합니다.

>>> ascii_unsupported.encode('ascii')

그러나이 코드를 실행하면 다음 오류가 발생합니다.

Output
Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character '\ufb06' in position 0: ordinal not in range(128)

ASCII에는 제한된 수의 문자가 있으며 Python은 ASCII 문자 집합에서 사용할 수 없는 문자를 찾으면 오류를 발생시킵니다. ASCII 문자 집합이 코드 포인트 \\ufb06를 인식하지 못하기 때문에 Python은 ASCII의 범위가 128이고 이 코드 포인트에 해당하는 10진수 값이 해당 범위 내에 있지 않다는 오류 메시지를 반환합니다.

encode() 함수에서 errors 인수를 사용하여 UnicodeEncodeError를 처리할 수 있습니다. errors 인수는 ignore, replacexmlcharrefreplace의 세 가지 값 중 하나를 가질 수 있습니다.

콘솔을 열고 다음을 입력하십시오.

>>> ascii_unsupported = '\ufb06'
>>> ascii_unsupported.encode('ascii', errors='ignore')

다음 출력을 얻을 수 있습니다

Output
b''

다음으로 다음을 입력합니다.

>>> >>> ascii_unsupported.encode('ascii', errors='replace')

출력은 다음과 같습니다.

Output
b'?'

마지막으로 다음을 입력합니다.

>>> ascii_unsupported.encode('ascii', errors='xmlcharrefreplace')

출력은 다음과 같습니다.

Output
b'&#64262;'

각각의 경우에 Python은 오류를 발생시키지 않습니다.

앞의 예에서 설명한 것처럼 ignore는 인코딩할 수 없는 문자를 건너뛰고 replace는 해당 문자를 ?로 바꾸고 xmlcharrefreplace는 는 인코딩할 수 없는 문자를 XML 엔터티로 바꿉니다.

UnicodeDecodeError 해결

UnicodeDecodeError는 지정된 인코딩으로 표현할 수 없는 문자가 포함된 문자열을 디코딩하려고 할 때 발생합니다.

이 오류를 생성하려면 바이트 문자열을 디코딩할 수 없는 인코딩으로 디코딩하려고 합니다.

콘솔을 열고 다음을 입력하십시오.

>>> iso_supported = '§'
>>> b = iso_supported.encode('iso8859_1')
>>> b.decode('utf-8')

다음과 같은 오류가 발생합니다.

Output
Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa7 in position 0: invalid start byte

이 오류가 발생하면 decode() 함수에서 errors 인수를 사용하여 문자열을 디코딩할 수 있습니다. errors 인수는 ignorereplace의 두 값을 허용합니다.

이를 시연하려면 Python 콘솔을 열고 다음 코드를 입력하십시오.

>>> iso_supported = '§A'
>>> b = iso_supported.encode('iso8859_1')
>>> b.decode('utf-8', errors='replace')

결과는 다음과 같습니다.

Output
'�A'

그런 다음 다음을 입력합니다.

>>> b.decode('utf-8', errors='ignore')

결과는 다음과 같습니다.

Output
'A'

이전 예제에서 decode() 함수의 replace 값을 사용하여 문자를 추가하고 ignore를 사용했습니다. 디코더(이 경우 utf-8)가 바이트를 디코딩할 수 없는 경우 아무 것도 반환하지 않았습니다.

문자열을 디코딩하는 동안 인코딩이 무엇인지 가정할 수 없습니다. 문자열을 디코딩하려면 인코딩 방법을 알아야 합니다.

결론

이 기사에서는 Python에서 유니코드를 사용하는 방법에 대한 기본 사항을 다뤘습니다. 문자열을 인코딩 및 디코딩하고 NFD, NFC, NFKD 및 NFKC를 사용하여 데이터를 정규화하고 유니코드 오류를 해결했습니다. 또한 정렬 및 검색과 관련된 시나리오에서 정규화 형식을 사용했습니다. 이러한 기술은 Python을 사용하여 유니코드 문제를 처리하는 데 도움이 됩니다. 다음 단계로 Python 3에서 코딩하는 방법을 읽을 수 있습니다.