PythonでLANG=Cのときのエンコーディングの注意


とあるPythonスクリプトを動かす環境のLANGがja_JP.UTF-8からCに変わったらエラーが出るようになったのでそのあたりの対処をメモ。

#!/usr/bin/python3
# -*- coding: utf8 -*-

import sys

from logging import getLogger, StreamHandler, DEBUG

handler = StreamHandler()

logger = getLogger(__name__)
logger.setLevel(DEBUG)
logger.addHandler(handler)


str = "ほげ"
tf = open('utf8.txt')
s = tf.read()

print(str)
print(s)

logger.debug(str)
logger.debug(s)

これをLANG=ja_JP.UTF-8で動かすのは大抵問題がない。これは大抵起動時にLANGを見て入出力のデフォルトエンコーディングを変更するようにPythonが設定されているからである。なのでこれをLANG=Cに持っていくとUTF-8をASCIIとして解釈しようとして例外を出すようになる。

まずファイルの読み込みにエンコーディングを指定する。

tf = open('utf8.txt', encoding='utf8')

printで使う sys.stdout の出力先がUTF-8であると指定する。

sys.stdout = codecs.getwriter("utf8")(sys.stdout.detach())
sys.stderr = codecs.getwriter("utf8")(sys.stderr.detach())

loggerはこのままでも動くがエスケープされた出力となってしまうので変更したsys.stderrを使うようにする。

handler = StreamHandler(sys.stderr)

まとめるとこうなる。

#!/usr/bin/python3
# -*- coding: utf8 -*-

import codecs
import locale
import sys


from logging import getLogger, StreamHandler, DEBUG, Formatter

sys.stdout = codecs.getwriter("utf8")(sys.stdout.detach())
sys.stderr = codecs.getwriter("utf8")(sys.stderr.detach())

handler = StreamHandler(sys.stdout)

logger = getLogger(__name__)
logger.setLevel(DEBUG)
logger.addHandler(handler)



str = "ほげ"
tf = open('utf8.txt', encoding='utf8')
s = tf.read()

print(str)
print(s)

logger.debug(str)
logger.debug(s)

参考