파이썬에서 UTF-8 파일에 쓰기


204

나는 정말로와 혼동된다 codecs.open function. 내가 할 때 :

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

그것은 나에게 오류를 준다

UnicodeDecodeError : 'ascii'코덱이 0 위치의 바이트 0xef를 디코딩 할 수 없습니다 : 서 수가 범위 내에 있지 않습니다 (128)

만약 내가한다면:

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

잘 작동합니다.

질문 은 왜 첫 번째 방법이 실패합니까? 그리고 어떻게 가슴을 삽입합니까?

두 번째 방법이 올바른 방법이라면 어떻게 사용 codecs.open(filename, "w", "utf-8")합니까?


54
UTF-8에서 BOM을 사용하지 마십시오. 부디.
tchrist

7
@tchrist 허? 왜 안돼?
Salman von Abbas

8
@SalmanPK BOM은 UTF-8에서 필요하지 않으며 복잡성 만 추가합니다 (예 : BOM으로 된 파일을 연결하고 유효한 텍스트로 결과를 만들 수 없음). 참조 이 Q & A를 ; Q에서 큰 의견 놓치지 마세요
로이스 Mahdal

답변:


271

문제는 그것이 codecs.BOM_UTF8유니 코드 문자열이 아닌 바이트 문자열 이라는 것 입니다. 파일 핸들러가 "Unicode를 UTF-8로 인코딩 된 텍스트로 작성하려고하는데 바이트 문자열을주었습니다!"

바이트 순서 표시 (예 : 유니 코드 U + FEFF)의 유니 코드 문자열을 직접 작성하여 파일이 UTF-8로 인코딩하도록하십시오.

import codecs

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

(정확한 대답을하는 것 같습니다-바이트가 EF BB BF 인 파일입니다.)

편집 : S. Lott 은 "utf-8-sig"를 인코딩하는 것이 BOM을 직접 작성하는 것보다 낫다는 제안 이지만, 이전에 무엇이 잘못되었는지 설명 하면서이 대답을 남겨 두겠습니다.


경고 : 열기와 열기는 동일하지 않습니다. "코덱에서 가져 오기 열기"를 수행하는 경우 단순히 "open"을 입력하는 것과 동일하지 않습니다.
Apache

2
당신은 또한 codecs.open 사용할 수 있습니다 ( 'W', 'TEST.TXT'을 'UTF-8-SIG') 대신
베타 - 폐쇄

1
"TypeError : 정수가 필요합니다 (유형 str)"가 표시됩니다. 우리가 여기서하고있는 일을 이해하지 못합니다. 누군가 도와주세요? 텍스트 파일에 문자열 (단락)을 추가해야합니다. 쓰기 전에 먼저 정수로 변환해야합니까?
Mugen

@ Mugen : 내가 작성한 정확한 코드는 내가 볼 수있는 한 잘 작동합니다. 어떤 코드를 가지고 있으며 오류가 발생하는 위치 를 정확하게 보여주는 새로운 질문을하는 것이 좋습니다 .
Jon Skeet

@ Mugen 당신 codecs.open은 그냥 대신 전화해야합니다open
northben

179

다음을 읽으십시오 : 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 ♭")

결과 파일은 예상 BOM이있는 UTF-8입니다.


2
감사. 작동했습니다 (Windows 7 x64, Python 2.7.5 x64). 이 솔루션은 파일 "a"(추가)에서 파일을 열 때 잘 작동합니다.
Mohamad Fakih

이것은 Windows의 Python 3에서 작동하지 않았습니다. 대신 bomfile : bomfile.write (codecs.BOM_UTF8)과 같이 open (file_name, 'wb')을 사용하여 파일을 추가 한 다음 추가 할 파일을 다시 열어야합니다.
더스틴 앤드류스

아마 추가 temp.close()?
user2905353

2
@ user2905353 : 필요하지 않습니다. 이것은의 컨텍스트 관리 에 의해 처리됩니다 open.
matheburg

11

@ S-Lott는 올바른 절차를 제공하지만 유니 코드 문제를 확장 하면 Python 인터프리터는 더 많은 통찰력을 제공 할 수 있습니다.

Jon Skeet은 codecs모듈 에 대해 옳지 않습니다 ( 바이트 문자열이 포함되어 있습니다).

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

다른 니트를 선택 BOM하면 표준 유니 코드 이름이 있으며 다음과 같이 입력 할 수 있습니다.

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

또한 다음을 통해 액세스 할 수 있습니다 unicodedata.

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

8

file * nix 명령을 사용하여 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()

1
기억하기 훨씬 쉬운 # coding: utf8대신 사용 # -*- coding: utf-8 -*-하십시오.
show0k
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.