2009-06-01 3 views
145

나는 codecs.open function과 정말로 혼동합니다. 내가 할 때 : 그것은 잘 작동Python으로 UTF-8 파일에 쓰기

file = open("temp", "w") 
file.write(codecs.BOM_UTF8) 
file.close() 

:

file = codecs.open("temp", "w", "utf-8") 
file.write(codecs.BOM_UTF8) 
file.close() 

을 내가 할 경우 오류를 나에게

UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)

을 제공합니다.

질문 첫 번째 방법이 실패하는 이유는 무엇입니까? 그리고 어떻게 뼈를 삽입합니까?

두 번째 방법이 올바른 방법 일 경우 codecs.open(filename, "w", "utf-8")을 사용하는 요점은 무엇입니까?

+40

에 알 수없는 문자 집합 파일을 변환 할 파일 * nix에서 스크립트 명령을 사용합니다. *** 제발. *** – tchrist

+6

@ tchrist 응?왜 안돼? –

+6

@SalmanPK BOM은 UTF-8에서 필요하지 않으며 복잡성 만 추가합니다 (예 : BOM 된 파일과 유효한 텍스트를 연결하는 것은 불가능 함). [이 Q & A] (http://stackoverflow.com/questions/2223882/whats-different-between-utf-8-and-utf-8-without-bom)를 참조하십시오. Q 아래에 큰 의견을 놓치지 마세요 –

답변

213

나는 codecs.BOM_UTF8이 유니 코드 문자열이 아닌 바이트 문자열이라는 것을 믿습니다. 나는 파일 처리기가 "나는 유니 코드를 UTF-8로 인코딩 된 텍스트로 쓰려고하는데, 바이트 문자열을 주셨다"라는 말을 근거로 생각하고 있습니다.

import codecs 

file = codecs.open("lol", "w", "utf-8") 
file.write(u'\ufeff') 
file.close() 

가 (즉, 정답을 줄 것 같다 있도록

바이트 순서 표시 (예 : 유니 코드 U + FEFF)의 유니 코드 문자열을 작성하려고 직접 파일은 UTF-8로한다는 인코딩 - 바이트 EF BB BF가있는 파일)

EDIT : S. Lott의 suggestion 인코딩은 "BOM"을 명시 적으로 작성하는 것보다 나은 방법이지만,이 답을 남겨 두겠습니다. 여기서 무엇이 잘못되었는지 전에 설명합니다.

+0

이것에 대해 많은 고마워, 명확하게 물건을 명확하게 만들었습니다 –

+0

경고 : 열 및 열기가 동일하지 않습니다. "코덱 가져 오기에서 열기"를 선택하면 단순히 "열기"라고 입력하는 것과 같지 않습니다. – Shiki

+0

대신 codecs.open ('test.txt', 'w', 'utf-8-sig')을 사용할 수도 있습니다. –

150

다음을 읽어 http://docs.python.org/library/codecs.html#module-encodings.utf_8_sig

with codecs.open("test_output", "w", "utf-8-sig") as temp: 
    temp.write("hi mom\n") 
    temp.write(u"This has ♭") 

결과 파일을 수행하는 UTF-8 예상 BOM에 있습니다. S-로트 @

+1

감사합니다. 그건 (Windows 7 x64, Python 2.7.5 x64). 이 솔루션은 파일을 "a"(추가) 모드로 열면 잘 작동합니다. –

+0

'import codecs' 먼저. – KrisWebDev

+0

Windows에서 파이썬 3이 작동하지 않습니다. 대신 bomfile : open (file_name, 'wb')을 사용하여이 작업을 수행해야했습니다. bomfile.write (codecs.BOM_UTF8) 그런 다음 파일을 다시 열어 추가합니다. –

11

오른쪽 절차를 제공하지만, 유니 코드 문제에 확장의 파이썬 인터프리터는 더 통찰력을 제공 할 수 있습니다. BOM 표준 유니 코드 이름이,

>>> import codecs 
>>> codecs.BOM 
'\xff\xfe' 
>>> codecs.BOM_UTF8 
'\xef\xbb\xbf' 
>>> 

다른 니트를 따기, 그것은으로 입력 할 수 있습니다 :

는 바이트 문자열이 포함 -

존 소총은 codecs 모듈에 대한 권리 (이상한)이다

>>> bom= u"\N{ZERO WIDTH NO-BREAK SPACE}" 
>>> bom 
u'\ufeff' 

그것은 unicodedata 통해서도 접근 :

>>> import unicodedata 
>>> unicodedata.lookup('ZERO WIDTH NO-BREAK SPACE') 
u'\ufeff' 
>>> 
+0

나는 당신의 정신을 간직하면서 당신의 대답을 풍성하게하려고 노력했습니다. – tzot

5

나는 UTF-8의 BOM을 사용하지 마십시오 UTF-8 파일

# -*- encoding: utf-8 -*- 

# converting a unknown formatting file in utf-8 

import codecs 
import commands 

file_location = "jumper.sub" 
file_encoding = commands.getoutput('file -b --mime-encoding %s' % file_location) 

file_stream = codecs.open(file_location, 'r', file_encoding) 
file_output = codecs.open(file_location+"b", 'w', 'utf-8') 

for l in file_stream: 
    file_output.write(l) 

file_stream.close() 
file_output.close() 
+0

요즘에는 [chardet] (https://pypi.python.org/pypi/chardet)도 사용할 수 있습니다. –

+0

기억하기 쉬운'# - * - coding : utf-8 - * -'대신'#coding : utf8'을 사용하십시오. – show0k