2010-07-10 14 views
1

잠시 동안 내 머리를 두드려 본 적이 있고 여러 기사를 읽었으며 문제가 더 명확하지 않습니다. 내 데이터베이스에 저장된 문자열의 무리를 가지고, 다음과 같은 상상 :파이썬 UTF8 문자열 혼동

x = '\xd0\xa4' 
y = '\x92' 

을 다음 내가 할 파이썬 쉘에서 :

내가보고 싶은 정확히 무엇
print x 
Ф 
print y 
? 

. 그러나 다음이있다 :

print unicode(x, 'utf8') 
Ф 

하지만이 :

unicode(y, 'utf8') 
UnicodeDecodeError: 'utf8' codec can't decode byte 0x92 in position 0: unexpected code byte 

내 느낌은 장고 유니 코드로 변환하려고하기 때문에 우리의 문자열이 망가지고있다,하지만 난 단지에 같은데요이다 이 점. 모든 통찰력이나 해결 방법이 감사합니다.

업데이트 : '\ x92'값이 포함 된 행의 데이터베이스를 보면이 문자가 '로 표시됩니다. 아포스트로피. 유니 코드 UTF-8 인코딩을 사용하여 데이터베이스의 내용을보고 있습니다.

+5

로 이동하여 내 문자 인코딩을 변경할 수 있습니다'y'는 유효한 UTF-8 인코딩 된 문자열이 아니다. 왜 파이썬이 이것을 디코딩 할 수있을 것으로 기대합니까? – Thanatos

+1

또한, 저는'x = '\ xd0 \ xa4' (추가 슬래시가 있습니다)라고 가정합니다. – Thanatos

+0

@ Thanatos. 나는 그것을 안다. 그러나 인코딩을 지정하지 않고 어떻게 인쇄 할 수 있습니까? 인코딩을 유추 할 수 있습니까? – dnolen

답변

4

ASCII 하위 집합 이외의 유니 코드 문자가 UTF-8로 멀티 바이트 표현을 가지고 있다고 생각했습니다. y은 char 당 단일 바이트 문자열로는 의미가 있지만 UTF-8 문자열로는 의미가 없습니다. 단일 바이트가 0x00에서 0x7F ASCII 범위를 벗어나기 때문에 코덱은 "실제"유니 코드 문자로 변환하기 위해 여분의 바이트 이상을 필요로합니다.

저는 이전에 파이썬에 익숙하지 않았습니다.하지만 저는이 답변에 확신이 없습니다.

EDIT 홉이 더 나은 답변입니다.

5

\x92은 유효한 utf-8 인코딩 문자가 아닙니다.

유니 코드 문자열로 디코드하려고 시도하기 전에는 xy에 간단한 (비 유니 코드) 문자열을 사용하므로 알지 못합니다. 그런 다음 인쇄 할 때 "그대로"터미널에 간단하게 덤프되며 터미널 자체는 해당 인코딩 설정에 따라 바이트를 해석합니다. 인코딩 (디코딩)의 경우 무엇을해야 하는지를 파이썬 오류를 알려줍니다 unicode()에 세 번째 매개 변수가

: 당신이 오타를 가지고있는 것처럼

>>> unicode('\x92', 'utf8', 'replace') 
u'\ufffd' 
>>> print _ 
� 
+0

@hop : "유니 코드 문자열로 디코드하려고 할 때까지 x 및 y에 대해 간단한 (비 유니 코드가 아닌) 문자열을 사용하기 때문에이를 알지 못합니다." - 그래서 단순한 비 유니 코드 문자열 "\ xd0 \ xa4"가 유니 코드 문자 U + 0424 CYRILLIC CAPITAL LETTER EF로 마술로 변형되었다고 말하는 것입니까? –

+1

@ 존 : 아니, 나는 전혀 말하지 않는다. 표시 할 유니 코드 문자에 유효한 utf-8 시퀀스를 디코딩하는 터미널에 관한 마술은 없습니다. 어떤 디코딩도하는 것은 파이썬이 아닙니다. – hop

+0

@ 존 : 터미널은 UTF-8로 구성되어 있기 때문에 터미널은 "\ xd0 \ xa4"를 U + 0424로 디코딩합니다. 일반적으로 요즘은 기본입니다. 그것이 다른 것으로 설정된 경우, 이것은 작동하지 않을 것입니다. – Thanatos

7

이 보이는; x = '\xd0\xa4'이어야합니다. 실제로 실행 한 내용과 출력에 나타난 내용을 복사하여 붙여 넣으면 도움이됩니다.

"\ x92"는 유효한 UTF-8 문자열이 아닙니다. 이것은 당신이 가진 예외를 설명합니다.

퍼즐의 더 많은 부분이 print y 인 이유는 ?입니다. "파이썬 콘솔"은 무엇이라고 부릅니까? 그것은 "대체"모드에서 작동하고 "?" ... 그게 평범한거야? " 흰색이 아닌 "?" 검은 다이아몬드 안에? 왜 그런 말을 해 "?" 정확히 당신이보기를 기대하는 것입니까?

업데이트 : 이제는 "" "너는 '\ x92'값이 들어있는 행에서 데이터베이스를 볼 때이 문자를 '아포스트로피'로 봅니다. 유니 코드 UTF-8 인코딩을 사용하는 데이터베이스입니다. "" "

아포스트로피가 아닙니다. 이 데이터 조각은 cp125X (일명 windows-125X) 인코딩 중 하나를 사용하여 인코딩 된 것으로 보입니다. CP1252을 사용하여 설명 (유주얼 서스펙트) :

IDLE 2.6.4  
>>> import unicodedata 
>>> uc = '\x92'.decode('cp1252') 
>>> print repr(uc) 
u'\u2019' 
>>> print uc 
’ 
>>> unicodedata.name(uc) 
'RIGHT SINGLE QUOTATION MARK' 
>>> 

대신 (그것이 의미하는 것은 무엇이나) "유니 코드 UTF-8 인코딩을 사용하여 데이터베이스의 내용을 볼"의를 추출하는 파이썬 코드의 작은 조각을 작성 시도 문제가되는 문자열을 입력 한 다음 print repr(bad_string)을 입력하십시오. 실행 한 코드와 repr()의 출력을 보여주십시오. 또한 Python의 버전, 플랫폼 (Windows 또는 Unix 기반) 및 데이터베이스 소프트웨어의 버전을 알려주십시오. 또한 CREATE TABLE 문에서 해당 열과 관련된 부분입니다.

thisthis도 읽으십시오.

+0

내가 이런 일이 일어날 것이라고 말하지 않았습니까? :) – hop

+2

@ 샵 : 아니, 당신은 다른 근본적인 문제가 있다고 의심했다. 그리고 그것은 태양이 동쪽에서 일어난다는 것을 의심한다고 말하는 것과 같았습니다 - OP는 거의 질문하지 말아야 할 질문을합니다. –

1
0x92 (hex) = 10 010010 (binary) 

UTF-8 일 010,010 바이트를 나타낼 수있는 바와 같이, "헤더"는 0이어야 (-> 00,010,010) 대신에도 10의 (이는 첫 번째 바이트의 헤더가 될 수 없다). 문자는 필요한 것보다 많은 바이트로 표현 될 수 없으므로 "\ x92"는 유효한 UTF-8로 인코딩 된 문자열이 아닙니다.

데이터베이스에 latin-1과 같은 일부 1 바이트 문자 인코딩이 사용 된 것 같습니다. 데이터베이스 쿼리를 직접 코딩하는 경우 연결 인코딩이 올바른지 또는 문자열이 올바르게 디코딩되는지 확인해야합니다. Django 모델을 사용하면 모든 것이 자동으로 작동합니다.

2

나는 당신이 혼란스러워하는 곳을 본다. 이것을 보자 :

x = '\xd0\xa4' 
y = '\x92' 

내가 print x 인 경우 나는 Ф를 얻는다. 이것은 내 터미널이 문자 인코딩으로 UTF-8을 사용하기 때문입니다. 따라서 D0 A4을 얻으면 UTF-8로 디코드하려고 시도하고 "Ф"를 얻습니다. ISO-8859-1 ("latin1")을 사용하기 위해 터미널을 변경하고 print x라고 말하면 터미널은 ISO-8859-1을 사용하여 D0 A4을 디코딩하려고 시도하고 D0 A4이기도하며 유효한 ISO -8859-1 문자열은 디코드되지만 이번에는 "¬ ¤"로 변경됩니다.

지금은 print y입니다. 이것은 UTF-8 문자열이 아니므로 터미널에서 디코딩 할 수 없습니다. 필자의 경우 " "를 인쇄하여이 오류를 알려줍니다. 나는 당신이 " "또는 "?"을 볼 수 있는지 궁금합니다. - 아마도 전자를 볼 수는 있지만, 출력이 나빠서 터미널이하는 일에 달려있다.

터미널의 인코딩은 $LANG과 일치해야하며 프로그램은 어떤 인코딩 으로든 데이터를 출력해야합니다. $LANG. 요즘에는 $LANG이 일반적으로 ???.UTF-8이며 ???이 다릅니다. (광산은 en_US.UTF-8입니다.)

이제 unicode(y, 'utf8')라고하면 파이썬은 이것을 UTF-8로 디코드하려고 시도하고 적절하게 예외를 throw합니다.

것은 내가 그놈 터미널을 사용하고, 터미널 → 문자 인코딩 설정

+0

답변입니다. 혼란을 해결해 주셔서 감사합니다. –