복붙노트

[PYTHON] 왜 utf8로 변환하지 않습니까?

PYTHON

왜 utf8로 변환하지 않습니까?

'\ xf1'과 같은 일부 문자를 출력하는 하위 프로세스 명령이 있습니다. 나는 그것을 utf8로 디코딩하려고하는데 오류가 발생합니다.

s = '\xf1'
s.decode('utf-8')

위의 throws :

UnicodeDecodeError: 'utf8' codec can't decode byte 0xf1 in position 0: unexpected end of data

그것은 '라틴 -1'을 사용할 때 작동하지만 utf8도 작동하지 않아야합니까? 나의 이해는 latin1이 utf8의 부분 집합이라는 것입니다.

내가 여기서 뭔가를 놓치고 있니?

편집하다:

print s # ñ
repr(s) # returns "'\\xa9'"

해결법

  1. ==============================

    1.유니 코드를 UTF-8과 혼동했습니다. Latin-1은 유니 코드의 하위 집합이지만 UTF-8의 하위 집합은 아닙니다. 개별 코드 단위에 대해 생각한 전염병을 피하십시오. 코드 포인트 만 사용하십시오. UTF-8에 대해 생각하지 마십시오. 대신 유니 코드에 대해 생각해보십시오. 이것은 당신이 혼란스러워하는 곳입니다.

    유니 코드를 UTF-8과 혼동했습니다. Latin-1은 유니 코드의 하위 집합이지만 UTF-8의 하위 집합은 아닙니다. 개별 코드 단위에 대해 생각한 전염병을 피하십시오. 코드 포인트 만 사용하십시오. UTF-8에 대해 생각하지 마십시오. 대신 유니 코드에 대해 생각해보십시오. 이것은 당신이 혼란스러워하는 곳입니다.

    파이썬에서 유니 코드를 사용하는 것은 매우 쉽습니다. 특히 Python 3과 넓은 빌드 (파이썬을 사용하는 유일한 방법)가 있지만 UTF-8을 고수 할 때주의해야한다면 좁은 빌드에서 레거시 Python 2를 사용할 수 있습니다.

    이렇게하려면 항상 소스 코드 인코딩과 출력 인코딩을 UTF-8로 올바르게 인코딩하십시오. 이제 UTF- 무엇이든 생각하지 마시고 Python 프로그램 전체에서 UTF-8 리터럴, 논리적 코드 포인트 번호 또는 기호 문자 이름 만 사용하십시오.

    다음은 행 번호가있는 소스 코드입니다.

    % cat -n /tmp/py
         1  #!/usr/bin/env python3.2
         2  # -*- coding: UTF-8 -*-
         3  
         4  from __future__ import unicode_literals
         5  from __future__ import print_function
         6  
         7  import sys
         8  import os
         9  import re
        10  
        11  if not (("PYTHONIOENCODING" in os.environ)
        12              and
        13          re.search("^utf-?8$", os.environ["PYTHONIOENCODING"], re.I)):
        14      sys.stderr.write(sys.argv[0] + ": Please set your PYTHONIOENCODING envariable to utf8\n")
        15      sys.exit(1)
        16  
        17  print('1a: el ni\xF1o')
        18  print('2a: el nin\u0303o')
        19  
        20  print('1a: el niño')
        21  print('2b: el niño')
        22  
        23  print('1c: el ni\N{LATIN SMALL LETTER N WITH TILDE}o')
        24  print('2c: el nin\N{COMBINING TILDE}o')
    

    다음은 ASCII 문자가 아닌 \ x {}} 표기법을 사용하여 고유 한 인쇄 기능입니다.

    % grep -n ^print /tmp/py | uniquote -x
    17:print('1a: el ni\xF1o')
    18:print('2a: el nin\u0303o')
    20:print('1b: el ni\x{F1}o')
    21:print('2b: el nin\x{303}o')
    23:print('1c: el ni\N{LATIN SMALL LETTER N WITH TILDE}o')
    24:print('2c: el nin\N{COMBINING TILDE}o')
    

    다음은 세 가지 방법 (a, b 및 c)을 보여주는 해당 프로그램의 샘플 실행입니다. 소스 코드의 첫 번째 집합 (StackOverflow의 NFC 변환이 적용되므로 신뢰할 수 없습니다!) !! !) 그리고 숫자 유니 코드 코드 포인트와 심볼 유니 코드 문자 이름을 가진 두 번째 세트는 각각 고유 한 것이므로 어떤 것이 실제로 있는지 볼 수 있습니다.

    % python /tmp/py
    1a: el niño
    2a: el niño
    1b: el niño
    2b: el niño
    1c: el niño
    2c: el niño
    
    % python /tmp/py | uniquote -x
    1a: el ni\x{F1}o
    2a: el nin\x{303}o
    1b: el ni\x{F1}o
    2b: el nin\x{303}o
    1c: el ni\x{F1}o
    2c: el nin\x{303}o
    
    % python /tmp/py | uniquote -v
    1a: el ni\N{LATIN SMALL LETTER N WITH TILDE}o
    2a: el nin\N{COMBINING TILDE}o
    1b: el ni\N{LATIN SMALL LETTER N WITH TILDE}o
    2b: el nin\N{COMBINING TILDE}o
    1c: el ni\N{LATIN SMALL LETTER N WITH TILDE}o
    2c: el nin\N{COMBINING TILDE}o
    

    바이너리를 보는 것을 정말 싫어하지만 바이너리 바이트처럼 보입니다.

    % python /tmp/py | uniquote -b
    1a: el ni\xC3\xB1o
    2a: el nin\xCC\x83o
    1b: el ni\xC3\xB1o
    2b: el nin\xCC\x83o
    1c: el ni\xC3\xB1o
    2c: el nin\xCC\x83o
    

    UTF-8 소스를 사용하는 경우에도 UTF-8의 직렬 표현의 밑에있는 개별 8 비트 코드 단위가 아닌 논리적 유니 코드 코드 포인트 번호 (또는 기호 이름있는 문자) 만 생각하고 사용해야합니다 (또는 UTF-16). 코드 포인트 대신 코드 단위가 필요하기는 매우 드물기 때문에 혼란 스럽습니다.

    선택 항목의 대안을 얻는 것보다 Python3의 광범위한 빌드를 사용하면 UTF-8이 아닌 UTF-32 문제가 더 안정적으로 작동합니다. UTF-32와 UTF-8은 모두 흐름을 따라 가면 쉽게 작업 할 수 있습니다.

  2. ==============================

    2.UTF-8은 Latin-1의 하위 집합이 아닙니다. UTF-8은 ASCII를 동일한 단일 바이트로 인코딩합니다. 다른 모든 코드 포인트의 경우에는 모두 여러 바이트입니다.

    UTF-8은 Latin-1의 하위 집합이 아닙니다. UTF-8은 ASCII를 동일한 단일 바이트로 인코딩합니다. 다른 모든 코드 포인트의 경우에는 모두 여러 바이트입니다.

    간단히 말하면 \ xf1은 UTF-8이 아닙니다. Python이 알려줍니다. "예기치 않은 입력 종료"는이 바이트가 제공되지 않은 멀티 바이트 시퀀스의 시작을 표시 함을 나타냅니다.

    나는 당신이 UTF-8을 읽을 것을 권한다.

  3. ==============================

    3.UTF-8의 멀티 바이트 시퀀스의 첫 번째 바이트이므로 자체적으로 유효하지 않습니다.

    UTF-8의 멀티 바이트 시퀀스의 첫 번째 바이트이므로 자체적으로 유효하지 않습니다.

    사실, 4 바이트 시퀀스의 첫 번째 바이트입니다.

    Bits Last code point Byte 1   Byte 2   Byte 3   Byte 4   Byte 5   Byte 6
    21   U+1FFFFF        11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    

    자세한 정보는 여기를 참조하십시오.

  4. ==============================

    4.잘못된. 라틴어 -1, ISO 8859-1 (때로는 Windows-1252로 잘못 표시 될 수도 있음)는 UTF-8의 하위 집합이 아닙니다. 한편, ASCII는 UTF-8의 서브 세트입니다. ASCII 문자열은 유효한 UTF-8 문자열이지만 일반화 된 Windows-1252 또는 ISO 8859-1 문자열은 유효한 UTF-8이 아니므로 s.decode ( 'UTF-8')가 UnicodeDecodeError를 던지고있는 것입니다.

    잘못된. 라틴어 -1, ISO 8859-1 (때로는 Windows-1252로 잘못 표시 될 수도 있음)는 UTF-8의 하위 집합이 아닙니다. 한편, ASCII는 UTF-8의 서브 세트입니다. ASCII 문자열은 유효한 UTF-8 문자열이지만 일반화 된 Windows-1252 또는 ISO 8859-1 문자열은 유효한 UTF-8이 아니므로 s.decode ( 'UTF-8')가 UnicodeDecodeError를 던지고있는 것입니다.

  5. from https://stackoverflow.com/questions/7163485/why-doesnt-this-conversion-to-utf8-work by cc-by-sa and MIT license