SSH で Python を実行したら UnicodeEncodeError になった

概要

ローカル環境で動作していた Python プログラムを Raspberry Pi にコピーして、 ローカル環境から SSH 経由でそのプログラムを実行したところ、 UnicodeEncodeError が発生しました。

確認環境

参考情報

解説

以下のプログラム (sample.py) を作成します。

print('\xa7')

IntelliJ IDEA の Terminal にて、Raspberry Pi Zero にコピーして、SSH で実行します。

intellij$ scp sample.py pi@raspberrypi.local:
intellij$ ssh pi@raspberrypi.local python3 sample.py
Traceback (most recent call last):
  File "sample.py", line 1, in <module>
    print('\xa7')
UnicodeEncodeError: 'ascii' codec can't encode character '\xa7' in position 0: ordinal not in range(128)

ちなみに、macOS の Terminal にて、同様に実行してもエラーは発生しません。 また、Raspberry PiSSH でログインしてから実行してもエラーは発生しません。

Terminal によって違うのは、環境変数に違いがあると思ったので比較すると、言語設定に違いが見られます。 上から順に、IntelliJ IDEA の Terminal、 macOS の Terminal、 IntelliJ IDEA の Terminal で Raspberri Pi に SSHmacOS の Terminal で Raspberry PiSSH

intellij$ printenv
LC_CTYPE=ja_JP.UTF-8
...
mac$ printenv
LANG=ja_JP.UTF-8
...
intellij$ ssh pi@raspberrypi.local printenv
LANG=en_GB.UTF-8
LC_CTYPE=ja_JP.UTF-8
...
mac$ ssh pi@raspberrypi.local printenv
LANG=en_GB.UTF-8
...

ローカル環境のロケールを確認します。

intellij$ locale -a | grep UTF-8
...
ja_JP.UTF-8
...

数が多いので、UTF-8 を文字に含む行だけを表示しています。 それでも、沢山のロケール名が表示されます。

Raspberry Pi Zero 環境のロケールを確認します。

intellij$ ssh pi@raspberrypi.local locale -a 
locale: Cannot set LC_CTYPE to default locale: No such file or directory
C
C.UTF-8
en_GB.utf8
POSIX

Raspberry Pi Zero 環境のロケールは全部で 4 つです。 LC_CTYPE をデフォルトロケールに使用できず、エラーが発生しています。 IntelliJ IDEA の Terminal では LC_CTYPE=ja_JP.UTF-8 ですが、ロケール ja_JP.UTF-8Raspberry Pi Zero 環境には存在していません。 ロケールの指定に問題があり UnicodeEncodeError が発生しています。

解決策の 1 つとしては、IntelliJ IDEA の Terminal で LC_CTYPE を unset する方法があります。

intellij$ unset LC_CTYPE

もしくは、適切な LC_CTYPE に設定すればよいでしょう。