特に、windowsのexcelでcsvが作成されていたりすると、エンコードが問題になることが良くあります。
このポストでは、この問題に対応する仕方をメモしておきます。。
1. 文字エンコードの復習。
*ASCII -- 最も基本的な文字コード。 半角英数字128文字から構成されており、全ての文字を1バイトで表します。例えば、「A」は、0x41(0xは16進数を表す。)
*UTF-8 -- 全ての文字を1~4バイトで表します。 世界中の文字を扱えるために、標準的に使われるようになりました。 Pythonの基本のエンコードになります。 UTF-8には、「バイト・オーダー・マーク(BOM)」の有無のオプションがあります。 (Excel形式を保持したい場合、「BOMあり」になります。)
Pythonで標準のcsvモジュールで、BOMありのUTF-8を読む場合は 、open()関数に encoding='utf_8_sig' と指定します。すると、最初の文字が '\ufeff ' になります。
逆にBOMなしUTF-8を指定して読むと、普通に読めて問題ありません。
*Shift-JIS -- パソコンで利用された日本語の文字コード。 全ての文字を2バイトで表します。
*Code Page932(cp932) -- Windows環境の日本語の文字コード。Shift-JISの一つのバリエーション。
2. CSVファイルのエンコードの判定
open()関数に、開きたいcsvが利用しているエンコードを指定しなくてはいけないので、どの文字コードを利用しているか判定するツール。
1) cardet を利用する。
(https://pypi.org/project/chardet/ )
これで判別できるのは、
2)自作のモジュールを利用する(未検証。 メモです。)
*getencモジュールのgetenc.getEncode()でファイルの文字コードの判別を行って、その文字コードをopen関数の引数として指定する。
enc = getenc.getEncode ('anycsvfilename.csv')
with open ('anycsvfilename.csv','r', encoding=en) as f:
など。
関数自身は、
http://myfuturesightforpast.blogspot.jp/2015/01/auto-detecting-japanese-file-encoding.html
参照。
3)Linuxサーバー上のコマンドで確認
> file -i [ファイル名]
# file -i 増減率一覧.csv
増減率一覧.csv: text/plain; charset=unknown-8bit ・・読み込めないファイル
# file -i prefectures.csv
prefectures.csv: text/plain; charset=utf-8
3. エラー対処
エラー表示
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position xx: invalid start byte
(0x8e: EUC_JPで使われる制御文字?)
① CSVを以下の読み込みの記述にする。
with open("myanyfilename.csv","r",newline='',encoding='utf_8') as f:
csv_reader=csv.DictReader(f)
*Python3.7 で、上記で読み込もうとした際のエラーメッセージ。
encoding='EUC_JP' とすると読める。
UnicodeDecodeError: 'cp932' codec can't decode byte 0xef in position 0: illegal multibyte sequence
① 以下のencoding用の記述で対処。
with open("start.csv","r", encoding='utf-8_sig') as f: #windows encoding用の記述
但し、(windows環境でutf-8にファイル自体を変えておかないと、この記述をしても、読み込みエラーになる場合もある。)
又、1つのファイルに複数のエンコード文字が入っていると、これだけで対処は難しい。
4.究極の対応。
Editorで、csvファイルを開いて、utf_8 フォーマットで保存する。
Excelだと、「csv(コンマ区切り)で保存。」だと、エンコードを変換してくれないが、
新しいExcel(少なくてもOffice365)では、、「csv utf-8 (コンマ区切り)で保存。」すれば、エンコードを変更してくれる。
csvのサイズも大きくないので、これで、今のところ正しく読みこみできるようになる。
いちいち、open関数の引数で、各々のエンコードを指定しなくても良いので、便利ではある。
自分で、Python csvモジュールでcsvを作成する場合、encoding='utf-8' を指定して書き込めば、
大丈夫。
以上 :)
0 件のコメント:
コメントを投稿