web-dev-qa-db-ja.com

PythonでUTF-8ファイルに書き込む

私は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()

正常に動作します。

質問最初の方法が失敗するのはなぜですか?そして、どうすればボムを挿入できますか?

2番目の方法が正しい方法である場合、codecs.open(filename, "w", "utf-8")を使用するポイントは何ですか?

175
John Jiang

問題は、 codecs.BOM_UTF8 がUnicode文字列ではなくバイト文字列であることだと思います。ファイルハンドラーは、「UnicodeをUTF-8エンコードテキストとして記述するつもりですが、バイト文字列を与えてくれました!」

ファイルがUTF-8としてエンコードするように、バイトオーダーマークのUnicode文字列(つまり、Unicode U + FEFF)を直接記述してみてください。

import codecs

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

(それは正しい答えを与えるようです-バイトEF BB BFのファイル。)

編集:S. Lottの suggestion エンコーディングとして「utf-8-sig」を使用することは、BOMを明示的に自分で書くよりも優れていますが、何が起こっているのかを説明するので、この答えを残します前に間違っています。

250
Jon Skeet

次をお読みください: 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です。

164
S.Lott

@ S-Lottは正しい手順を示しますが、Unicodeの問題、Python通訳者はより多くの洞察を提供できます。

Jon Skeetは codecs モジュールについて正しい(珍しい)です-バイト文字列が含まれています:

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

別のnitを選択すると、BOMには標準Unicode名があり、次のように入力できます。

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

unicodedata からもアクセスできます:

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

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()
8
Ricardo