Pythonで日本語のエンコードエラーが発生したときの対応策
|
Pythonで日本語を使っていたら、下記のような日本語の文字コードエラーが発生しました。
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)
解決策をまとめます。
原因
正確に理解しているかわからないのですが、一応簡単に調べました。
Python3では、デフォルトで ANSI_X3.4-1968
というエンコード方式が標準入出力で使われているようです。
>>> import sys, io
>>> sys.stdout
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='ANSI_X3.4-1968'>
これはASCII型に変換してくれるものですが、
- 日本語は非ASCII文字
- 日本語の結合をしたりするときにデコードが必要
- しかしPythonの文字列は自身のエンコードに関する情報を持っていない
- 日本語を無理やりASCII型でデコードしようとする
という感じでエラーが発生するようです。つまり、エンコード方式 にutf-8
を指定すれば良い。以下、対応策です。
対応策1…ファイルの冒頭でエンコーディング方式を指定
下記の行をファイルの冒頭に追記します。
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
とりあえずこれを記述しておけば安心、という考えはバグの温床になりやすいので危険ですが、おそらくこれが一番簡単な方法なので、日本語を扱うときはこれを入れておくといいと思います。
対応策2…実行時にエンコーディング方式を指定
インタプリタでPythonのコードを実行する場合限定ですが、下記のように PYTHONIOENCODING
という環境変数を指定することで、標準入出力のエンコーディングを上書きできます。
PYTHONIOENCODING=utf-8 python3 hogehoge.py
対応策3…環境変数を設定
毎回対応策2のように指定するぐらいなら、最初から設定しておけば楽チンです。
export PYTHONIOENCODING=utf-8
↑これを~/.bash_profileに追記します。dockerの場合はdockerfileに ENV PYTHONIOENCODING utf-8
を追記すればOKです。
まとめ
近年は自然言語処理などで日本語を扱うケースが増えてきているのかなと思いますが、日本語周りのエラーには悩まされそうです。