Python でも 「Mac を使っているなら必ず使うべき2つの機能 "Automator" と "サービス"」

2013/03/23 22:59

※ 商品のリンクをクリックして何かを購入すると私に少額の報酬が入ることがあります【広告表示】

a2cが「 これ と同じ事をPythonでやりたいけど、”python -c" じゃ動かない罠。」と ぼやいていた ので悔しいのでやってみた。

そもそもの Automator と サービス の使い方は 元ネタ がわかりやすいので読んでもらうとして。

とりあえずやってみる

単純に 10.times{print 'リア充'} に限定すれば、 ruby -Ku のかわりに、

python -c "import sys;print(eval(sys.argv[1]))" "$*"

を Automator に設定して、「入力の引き渡し方法」を「引数として」にすれば、任意のテキストを編集できるアプリケーションで次のようなテキストを選択、サービスを起動すれば同じ結果になる(別にstdinのままで sys.stdin.read() でも良いけど)。

'リア充' * 10

ただし、もう少し複雑にするとprintできなくなる。例えばこんな感じの文字は評価結果をうまくプリントできない。

a, b = 1, 2;a * b

そもそもevalに渡した時点でエラーになる。

では、execを使ったらどうか。試しにインタラクティブシェルで実行してみる。

>>> exec('a, b = 1, 2;a * b')
>>>

当然だけど、実行結果がとれない。インタラクティブシェルで単純に評価させている場合には、sys.display_hookの機能で _ に最後の評価結果が入るんだけど、それでさえもexecした結果は入らない(aやbはきちんとlocals()で存在確認できるし、値も確認できる)。

さてさて、困りました。

どうにかして最後に評価した値を取得したい。

実行フレームからたどるとか?無理矢理pdb上で実行していくとか?うーん。

インチキ臭いやり方に逃げる

compile という組み込み関数があります。

python -c "import sys;exec(compile(sys.argv[1], '', 'single'))" "$*"

これで、少し複雑なコードを書いても思った通りの結果が返ってきます。lambdaくらいならいけるっぽい(意味があるかはおいておいて)。

egg = lambda x:x * 10;egg('パーフェクトPython買うでしょ!今でしょ!')

compile は、コード片をPythonのコードオブジェクトに変換する関数です。evalやexecに何度も同じ構文解析をさせる必要がある場合には、事前にコードオブジェクトにして無駄を減らせるというのが本来の使い方です。

このcompile関数の第3引数に 'single' を渡すと評価結果が None 以外だった場合に結果を出力してくれるというなんとも都合の良いものです。

結果は…

'\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x95\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88Python\xe8\xb2\xb7\xe3\x81\x86\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81\xe4\xbb\x8a\xe3\x81\xa6\xe3\x82\x99\xe3\x81\x97\xe3\x82\x87\xef\xbc\x81'

うぉーい。そもそも、なんかシングルクォートでくくられてる…。

実はやり過ぎてた

よく元ネタを見てみると 、しっかりprint文まで書いたものを選択していて、何の苦労をしていたのかはよくわからない。

よって、こうして…

python -c "import sys;exec(sys.argv[1])" "$*"

print文を使うのが吉

egg = lambda x:x * 10;print(egg('パーフェクトPython買うでしょ!今でしょ!'))

もちろん、python3でも

Python3だともう少し増えて…(ターミナルならこんなことしなくても動作するのでキモい)

/usr/local/bin/python3 -c "import sys;import io;sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf8');exec(sys.argv[1])" "$*"

うむ(ちなみに、Python 2系は2.7.2、Python 3系は3.3.0で試してみた。python3はインストーラで入れただけではAutomatorの使うシェルからPATHが通ってないのでフルパス書いてる)。

だがしかし、テキストエディットとかなら思った通りだけれど、sublimetext3とか日本語に弱いエディタだとちょいとおかしなことが…。

sublimetext3はそもそもpython3.3搭載でPythonでプラグイン書いて何でもできるからAutomatorなんていらんしいいか。

Prev Entry

Next Entry