2013-06-24 4 views
7

파이썬의 UTF-8 인코딩 (codecs 패키지)은 유니 코드 문자 28, 29 및 30을 줄 끝으로 해석합니다. 왜? 어떻게 그렇게하지 못하게 할 수 있습니까?파이썬 코덱 줄 끝

예제 코드 : 여기

with open('unicodetest.txt', 'w') as f: 
    f.write('a'+chr(28)+'b'+chr(29)+'c'+chr(30)+'d'+chr(31)+'e') 
with open('unicodetest.txt', 'r') as f: 
    for i,l in enumerate(f): 
    print i, l 
# prints "0 abcde" with special characters in between. 

요점은 내가 할 것으로 기대대로 한 줄로을 읽는 것입니다. 이제 codecs을 사용하여 UTF-8로 읽을 때, 그것을 여러 줄로 해석합니다.

import codecs 
with codecs.open('unicodetest.txt', 'r', 'UTF-8') as f: 
    for i,l in enumerate(f): 
    print i, l 
# 0 a 
# 1 b 
# 2 c 
# 3 de 
# (again with the special characters after each a, b, c, d 

문자 28-31은 "정보 분리 기호 4"- "1"(이 순서대로)로 설명됩니다. 두 가지가 나에게 충격을 준다. 1) 28 ~ 30은 줄 끝으로 해석되고, 2) 31은 그렇지 않다. 이것은 의도 된 행동입니까? 어떤 문자가 줄 끝으로 해석되는 정의는 어디에서 찾을 수 있습니까? 라인 끝으로 해석하지 않는 방법이 있습니까?

감사합니다.

편집codecs.open에 'UTF-8'인수를 복사하는 것을 잊었습니다. 내 질문에 코드가 수정되었습니다.

+0

파일을 'rb'모드로 열면 어떻게됩니까? – unutbu

+0

차이가 없습니다. – Paul

+2

@Paul, 자신 만의 질문에 대답 할 수 있으며 원하는 경우 동의 할 수 있습니다. –

답변

5

위대한 질문입니다.

open() 또는 codecs.open()을 사용하여 파일을 여는 것이 효과적입니다. 전자는 바이트 문자열의 관점에서 작동합니다. 후자는 유니 코드 문자열의 관점에서 작동합니다. 파이썬에서는 behave differently입니다.

동일한 질문이 Python Issue 7643, What is a Unicode line break character?으로 나타났습니다. 토론과 Unicode Character Database에 대한 인용문은 흥미 롭습니다. 또한 이슈 7643에서는이 간결한 코드 스 니펫을 통해 차이점을 보여줍니다.

for s in '\x0a\x0d\x1c\x1d\x1e': 
    print u'a{}b'.format(s).splitlines(1), 'a{}b'.format(s).splitlines(1) 

그러나이 점에 달려 있습니다.

바이트 문자열의 바이트가 줄 바꿈 (또는 공백)인지 확인하려면 Python은 ASCII control characters 규칙을 사용합니다. 이 측정 값에 따라 바이트 10과 13은 줄 바꿈 문자입니다 (파이썬은 바이트 13을 처리하고 10을 한 줄 바꿈으로 처리합니다).

유니 코드 문자열의 문자가 줄 바꿈 있는지 확인하기 그러나

는, 파이썬과 UAX #14 Line Breaking Algorithm, section 5 Line Breaking Properties의, UAX #44에 설명 된 Unicode Character Database의 문자 분류를 따릅니다.

  • 일반 카테고리의 Z1 "라인 구분자"
  • 일반 카테고리 Zp에 "단락 구분"
  • 양방향 등급 : 문제 7643에 따르면,이 문서는 파이썬의 목적 LINEBREAK로 문자를 식별하는 세 가지 문자 속성을 식별 B "단락 구분 기호"

문자 28 (0x001C), 29 (0x001D) 및 30 (0x001E)에는 이러한 문자 속성이 있습니다. 문자 31 (0x001F)은 그렇지 않습니다. 왜? 이것이 유니 코드 기술위원회의 질문입니다. 그러나 ASCII에서 이러한 문자는 "파일 구분 기호", "그룹 구분 기호", "레코드 구분 기호"및 "단위 구분 기호"로 알려져 있습니다.탭 텍스트 데이터 파일을 비교로 사용하면 처음 세 개는 줄 바꿈만큼의 분리를 의미하지만 넷째는 아마도 탭과 유사합니다.

실제로이 세 유니 코드 문자를 파이썬 유니 코드 문자열의 줄 바꿈으로 정의하는 코드는 Objects/unicodeobject.c입니다. 배열 ascii_linebreak[]을 찾으십시오. 이 배열은 unicode.splitlines() 구현의 기초가됩니다. 다른 코드 밑줄 str.splitlines(). 나는 믿지만 파이썬 소스 코드에서 추적하지는 않았지만, codecs.open()으로 열린 파일의 enumerate()유니 코드.splitlines()으로 구현되었다.

"어떻게 그렇게 할 수 없습니까?" splitlines()의 동작 방식이 다르게 나타납니다.

with open('unicodetest.txt', 'r') as f: 
    for i,l in enumerate(f): 
    print i, l.decode('UTF-8') 
# prints "0 abcde" with special characters in between. 

난 당신이 파이썬이 사용하는 가정 : 그러나, 당신은 str.splitlines() 행동 바이트로 라인을 읽어 바이트 스트림으로 파일을 열 수 있습니다, 다음 유니 코드 문자열로 사용하기 위해 UTF-8로 각 라인을 디코딩 .x, 3.x가 아닙니다. 내 대답은 Python 2.7을 기반으로합니다.

+1

감사합니다. 이것은 정교합니다. 그리고 당신의 솔루션에 감사드립니다. 말이된다. – Paul