pythonのprintで日本語の出力がデフォルトで出来ない。

投稿者: Anonymous

pythonで単純に日本語をprintしようとしたら、エラーになってしまいます。

# -*- coding: utf-8 -*-
try:
    print("あああ")
except Exception as e:
    print(e)

実行結果

'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

pythonのバージョン

# python -V
Python 3.6.0 :: Anaconda 4.3.1 (64-bit)

下記の3行を追加すればエラーは治りますが、普通この3行は不要だと思います。
この3行を記述する事なく日本語をprintしたいのですが、どうすれば良いでしょうか?

import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

[追記]
ちなみにsys.stdout.encodingのデフォルト値は「ANSI_X3.4-1968」でした。

# python
Python 3.6.0 |Anaconda 4.3.1 (64-bit)| (default, Dec 23 2016, 12:22:00)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.stdout.encoding)
ANSI_X3.4-1968

[追記2]
LANGは指定無し、LC_CTYPEはPOSIXでした。

# locale
LANG=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

[追加3]
localeを変更してもエラーメッセージが出てきて、うまくいきませんでした。

# export LANG=ja_JP.UTF-8
# locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=ja_JP.UTF-8
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=

# LANG=ja_JP.UTF-8 python -c 'import sys; print(sys.stdout.encoding)'
ANSI_X3.4-1968
# LANG=en_US python -c 'import sys; print(sys.stdout.encoding)'
ISO-8859-1

# python
Python 3.6.0 |Anaconda 4.3.1 (64-bit)| (default, Dec 23 2016, 12:22:00)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.stdout.encoding)
ANSI_X3.4-1968
>>> print("aaa")
aaa
>>> print("���������")
  File "<stdin>", line 0

    ^
SyntaxError: 'ascii' codec can't decode byte 0xe3 in position 7: ordinal not in range(128)
>>> print("あああ")
  File "<stdin>", line 0

    ^
SyntaxError: 'ascii' codec can't decode byte 0xe3 in position 7: ordinal not in range(128)
>>>

解決

Windows の場合はコンソールのコードページを、それ以外の場合はロケールを日本語向けに設定してください。環境変数 PYTHONIOENCODING でも設定できますが、コンソールのエンコードと食い違う可能性があります。

sys.stdout というストリームはプラットフォームごとに用意されている特別なテキストファイルのようなものであり、従って互換性のためエンコーディングもプラットフォーム依存にしているのでしょう (残念ながら、デフォルトでは UTF-8 で解釈しないコンソールもあるのです)。ドキュメントにも以下のように書かれています。

これらのストリームは open() が返すような通常の テキストファイル です。引数は以下のように選択されます:

  • 文字エンコーディングはプラットフォーム依存です。Windows では、ストリームが対話型 (isatty() メソッドが True を返す場合) であれば、コンソールのコードページが、それ以外では ANSI コードページが使用されます。その他のプラットフォームでは、ロケールのエンコーディングが使用されます (locale.getpreferredencoding() を参照)。

    しかしながら、どのプラットフォームでも Python を起動する前に環境変数 PYTHONIOENCODING を設定することでこの値を上書きすることが出来ます。

ロケールによってもエンコーディングが変わるのは不思議かもしれませんが、ロケールにはコードセットも指定できるため (例: en_US.UTF-8)、しょうがないです。自分が使いたい適切なロケールを設定しましょう。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *