#はじめに
python を始めようと思って、まあ、そこはやっぱり
print("Hello world")
うん、よしよし。
print("日本語")
Traceback (most recent call last):
File "/tmp/a.py", line 1, in <module>
print("\u65e5\u672c\u8a9e");
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
#普通の解決策
いろいろ、ググッて調べたところ、unicode と byte の変換をしなきゃイカン、ということで
print("日本語".encode("utf-8"))
b'\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e'
いや、だからそうじゃなくてね。
setenv LANG ja_JP.UTF-8
日本語
まあ動いたわけですよ。しかしさらなる問題が!
#cron から起動したいんだが
cron 起動する場合は、親プロセスが cron なので、当然 cron の環境を引き継ぐわけです。それは、システム全体としてどういうロケールに設定しているかと言う話。しかし、システム全体は基本 C で統一しているポリシーなので(ls とか date を日本語ロケールフォーマットにされると、いろいろ動かなくなる)、cron の環境も当然 LANG=C なの。それは変えられないの。
#余談:shebang
スクリプト起動するために、1行めに #! /usr/local/bin/python3
とか書きますよね。これ、呼び方はいろいろあるんだけど、シェバン(shebang)というらしい。で、これで呼び出されるものは、2重に shebang が使えない。つまり、#! /usr/local/bin/foo
のとき、/usr/local/bin/foo の1行めが、#! /usr/local/bin/bar
だとダメだ、ということ。知らんかった。たぶんシステムコール中で exec()系列の関数を呼び出しているということなんだろう。
#環境変数をセットして起動したい
/usr/local/bin/python3 を、シェルスクリプトにする案は挫折したので、しょうがなく C で書きました。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv){
putenv("LANG=ja_JP.UTF-8");
argv[0] = "/usr/local/bin/python3.5";
argv[argc] = NULL;
execv("/usr/local/bin/python3.5",argv);
}
これで、最初の print("日本語")
のみで動作するようになりました。(encodeがいらなくなった)
python3 がシンボリックリンクではなくなりましたが、無理やりの対応策ですのでご勘弁。
なんとか解決。
Pythonista への道は険しい