web-dev-qa-db-ja.com

Pythonでファイルのエンコーディングを知る方法は?

Pythonでファイルのエンコーディングを取得する方法を知っている人はいますか?コーデックモジュールを使用して特定のエンコーディングでファイルを開くことができることは知っていますが、事前に知っておく必要があります。

import codecs
f = codecs.open("file.txt", "r", "utf-8")

ファイルに使用されているエンコーディングを自動的に検出する方法はありますか?

前もって感謝します

編集:非常に興味深い回答をありがとうございました。また、chardetに基づく http://whatismyencoding.com/ にも興味があるかもしれません(サイトの詳細はbottle pythonフレームワーク)を利用しています)

24
luc

残念ながら、ファイル自体を調べてファイルのエンコーディングを決定する「正しい」方法はありません。これは普遍的な問題であり、pythonまたは特定のファイルシステムに限定されません。

XMLファイルを読んでいる場合、ファイルの最初の行mightは、エンコーディングが何であるかについてのヒントを提供します。

それ以外の場合は、 chardet (他の回答で示されているソリューションの1つ)のようなヒューリスティックベースのアプローチを使用する必要があります。 Windowsを使用している場合、Windows APIは、ファイル内のデータに基づいてエンコードを推測するためのメソッドも公開していると思います。

23
HS.

BOM( http://en.wikipedia.org/wiki/Byte_order_mark )を使用してエンコードを検出するか、次のライブラリを試してください。

https://github.com/chardet/chardet

9
ZelluX

これは、エンコーディングを推測するのに役立つ小さなスニペットです。 latin1とutf8の間はかなり良いと思います。バイト文字列をUnicode文字列に変換します。

# Attention: Order of encoding_guess_list is import. Example: "latin1" always succeeds.
encoding_guess_list=['utf8', 'latin1']
def try_unicode(string, errors='strict'):
    if isinstance(string, unicode):
        return string
    assert isinstance(string, str), repr(string)
    for enc in encoding_guess_list:
        try:
            return string.decode(enc, errors)
        except UnicodeError, exc:
            continue
    raise UnicodeError('Failed to convert %r' % string)
def test_try_unicode():
    for start, should in [
        ('\xfc', u'ü'),
        ('\xc3\xbc', u'ü'),
        ('\xbb', u'\xbb'), # postgres/psycopg2 latin1: RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
        ]:
        result=try_unicode(start, errors='strict')
        if not result==should:
            raise Exception(u'Error: start=%r should=%r result=%r' % (
                    start, should, result))
4
guettli

nicode Dammit from Beautiful Soup があり、これは chardet を使用しますが、いくつかの追加機能を追加します。

XMLまたはHTMLファイル内からエンコーディングを読み取ろうとします。次に、ファイルの先頭でBOMなどを検索しようとします。それができない場合は、 chardet を利用します。

3
Craig McQueen
#!/usr/bin/python

"""
Line by line detecting encoding if input and then convert it into UTF-8
Suitable for look at logs with mixed encoding (i.e. from mail systems)

"""

import sys
import chardet

while 1:
        l = sys.stdin.readline()
        e = chardet.detect(l)

        u = None
        try:
                if e['confidence'] > 0.3:
                        u = unicode(l, e['encoding'])
        except:
                pass

        if u:
                print u,
        else:
                print l,