.. title:: Pythonで心理実験 - 例題10-2
例題10-2:IPythonを使う
==================================
.. note::
+ 追記(2014/07/23)
+ この記事はIPython 0.10に基づいて書かれたものです。IPython 2.1を用いた解説が :doc:`例題22-2 <22-2>` にありますので合わせてご覧ください。
**A:** さて、そんなわけで早速IPythonの使い方だ。 IPythonは `http://ipython.scipy.org/moin/ `_ からダウンロード出来る。 それにしてもIPythonのURLってscipyなんだよな。ぶつぶつ。
**B:** scipy?
**A:** ああ、scipyはいずれ説明することになるんで今は置いといて、と。 例によってLinuxで使ってる人は自分でわかるでしょ、で終了。Windowsなら、左のメニューのDownloadをクリックしてA binary Windows Installerを選べばよい。 eggからのインストールが分かる人はeggをダウンロードしてもいい。
.. figure:: img/10-2-01.png
**B:** はあ、なんだかわかりませんのでA binary Windows installerてのをダウンロードします。 …っと、ipython-0.10.win32-setup.exeファイルがダウンロードされましたけど、これをダブルクリックすればいいんですか?
**A:** そう。(振り返って)この記事を書いている2010年6月の時点ではバージョン0.10のインストーラが公開されていますが、 新しいバージョンが公開されたらファイル名も変わると思いますんでご了承くださいね。
**B:** 誰に向かって話してるんですか。えーと、カチカチ。…終わりました。これだけ?
**A:** これだけ、と言いたいところだが、Windowsを使っている人にはぜひもうひとつ入れてほしいパッケージがある。 pyreadlineだ。
**B:** ぱ、pyread…、なんですって?
**A:** pyreadline。上述のIPythonのWikiのトップページにリンクを表示してくれりゃいいんだが、なぜか表示されていない。 `http://ipython.scipy.org/moin/PyReadline/Intro `_ へアクセスすりゃページが開く。 ダウンロードだけならさっきのIPythonのダウンロードのページから旧バージョンのダウンロードディレクトリを開いてもダウンロードすることができる。 2010年6月8日現在のバージョンは1.5だ。
**B:** うーん、ややこしいなあ。カチカチ。
.. figure:: img/10-2-02.png
**B:** …インストール完了。ところでこのpyreadlineってなんですか?
**A:** Windowsのコマンドプロンプト(cmd.exe)ってのは、Linuxとかのコマンドシェルを使ってる人から見ると編集機能やらなんやらが見劣りするんだよな。 cmd.exeも昔のMS-DOSとかWindows95の頃に比べるとずっと良くなっているんだけどね。
**B:** またおっさんの昔話が始まった…
**A:** ん?何か?
**B:** いや、別になにも。
**A:** …。まあいい。とにかく、pyreadlineというのはWindowsのpythonインタプリタの能力を拡張してくれるものだ。 こいつがあるとIPythonがさらに便利に使えるんで、入れない手はない。
**B:** はあ。
**A:** インストールがすんだらWindowsのスタートメニューのプログラムを見て。IPythonというグループが追加されているはず。 いろいろアイコンが並んでるけど、ここではとりあえずIPythonを選んで起動。
**B:** はーい。
.. figure:: img/10-2-03.png
.. figure:: img/10-2-04.png
**B:** ええと、この殺風景な真黒いのがIPythonですか。
**A:** ん。他に言いようはないのか。 緑色の文字が表示されてたりしてちっとは華やかになってるだろ。pyreadlineが入ってなかったらモノクロになっちまうが。 とにかく、ここにpythonのコマンドを打ち込んでpythonに仕事をしてもらう。基本的には普通のpythonインタプリタと同じだな。In [1]:てのが今までのpythonインタプリタの">>>"の代わり。 入力したコマンドに対する出力にはOut [1]:てな具合に赤い見出しがつく。 区別しやすいだろ。 さて、まずは補完機能を使ってみるか。import VisionEgg.と入力してTabを押してみなさい。
**B:** VisionEgg.? ピリオドで止めるんですか?
**A:** そのとおり。
**B:** …、Tabっと。おおお。なんかずらずらっと出てきた。
**A:** IPythonが「VisionEgg.なんちゃら」という名前のモジュールをリストアップしてくれたのさ。 一番下の行にB君が入力したimport VisionEgg.ってのが残ってるから、ピリオドの後にCと一文字入れてまたTabを押してごらん。
**B:** 今度はVisionEgg.CoreとVisionEgg.Configurationの二つになりましたね。
**A:** 「VisionEgg.Cなんちゃら」ってモジュールがその二つしかないってことだな。 おまけにどちらもVisionEgg.Coまでは同じなんで、一番下の行ではちゃんとCの後にoが補われている。
**B:** うーん、なかなか賢いなあ。
.. figure:: img/10-2-05.png
**A:** こういうのを **補完機能** という。便利だろ。じゃあ今度はimport VisionEgg.Coreまで入力してEnterを押して。
**B:** 押しました。
**A:** そこでさらにVisionEgg.Core.まで入力してTab。
**B:** またずらずらっと出てきましたね。
**A:** 今度はVisionEgg.Coreのデータ属性やメソッドがずらずらっと表示される。 それはさっきと同じようなもんだね。今度はhelp(VisionEgg.Core)と入力してEnterを押して。
**B:** help(VisionEgg.Core)、と。おお、なんですかこれ。
**A:** 見ての通り、VisionEgg.Coreのヘルプが表示されているのさ。()は省略することもできる。 今までVisionEggを始めいろんなモジュールにどんなメソッドがあるのか、メソッドにはどのような引数が必要なのかといった事を調べる方法を全然解説してこなかったけど、 こうすれば調べることができる。あ、ちなみに一番下の行に-- MORE --と表示されている場合は続きがあるのでSpaceキーを押して読み進めてくれ。途中でやめたい場合はqね。
**B:** へえ、IPythonって便利ですねえ! ていうか、helpくらい標準で見られたらいいのに。
**A:** いや、helpはIPythonを入れなくても見られる。
**B:** へ? そんなこと教えてもらいましたっけ?
**A:** 教えてない。けど、pythonインタプリタ立ち上げたら最初に"Type "help", "copyright", "credits" or "license" for more information."って出るだろ。 IPythonが入っていない場合は()を省略出来ないこと以外、機能的には同じ。
**B:** なんで早く教えてくれないんですか!
**A:** テキトーにやってたら忘れてたってのが第一。 それと、IPythonがなかったらモジュールやメソッドの一覧を表示する機能が働かないから、モジュールやメソッドの名前を知っていないと結局ヘルプを使うことが出来ない。 やっぱりIPythonの補完機能さまさまというわけだ。
**B:** ぶーぶー。
**A:** 補完機能は変数名などにも働く。例えばInterStimulusInterval03という変数があるとする。 いちいち全部入力するのは面倒くさいので、InterくらいまでTabを押せば、後は勝手にIPythonが補完してくれる。 もちろんInterTrialInterval02とかいう変数や関数もある場合は、該当する名前がリストアップされる。
**B:** ぶーぶー。
**A:** 補完は何か一文字入力しないと働かない。 何も入力せずにTabを押すとファイル名の補完が起るんだが、それはまたすぐ後で説明する。 そもそも今どんな変数があるの?という時には **whos** というコマンドを入力してEnterを押せばいい。 そうすると、現在pythonが覚えている「名前」がずらずらと表示される。整数や文字列といった変数の値のタイプも表示してくれるから便利だ。
**B:** ぶーぶー。
**A:** さて、補完の話はこのへんにしておいて、cd、ls、runの話をしておくか。
**B:** …とことん無視する気ですね?
**A:** おうよ、講義やらなんやらの合間の細切れの時間でちまちま書いてるから考えてらんな…じゃなくて、ごほごほ。 ただでさえ無駄話ばかりなんでな。しゃきしゃき行かないと誰も読んでくれなさそうだから。
**B:** Aさん、それも舞台裏。
**A:** えー、あー。とにかく。とにかく、次はcd。B君はコマンドプロンプトのcdコマンドを知っているか?
**B:** 昔習いましたよ。ええと…なんだっけ。
**A:** カレントディレクトリを変更するんだよ。
**B:** ああ、それそれ。カレントディレクトリにあるファイルはファイル名だけで開けるんでしたっけ。
**A:** んー。まあだいたい正解かな。 :doc:`例題4-2 <04-2>` でもちょっとだけ触れたんだけど、pythonでカレントディレクトリを調べるにはosというモジュールをインポートして os.getcwd()を使う。カレントディレクトリを変更するにはos.chdir()だな。
.. code-block:: ipythonconsole
In [2]: import os
In [3]: os.getcwd()
Out[3]: 'C:\\Users\\A'
In [4]: os.chdir('Documents')
In [5]: os.getcwd()
Out[5]: 'C:\\Users\\A\\Documents'
**B:** ふむふむ。
**A:** IPythonでは、osをimportしなくてもコマンドプロンプトと同じようにcdというコマンドが使える。
.. code-block:: ipythonconsole
In [6]: cd
Out[6]: 'C:\\Users\\A'
In [7]: cd Documents
Out[7]: 'C:\\Users\\A\\Documents'
**B:** へえ。ちょっとしたことですが()とか''とか入れなくていいのは楽ですね。
**A:** そうだろ? ちょっと気をつけなきゃならんのは、cdとだけ入力するとWindowsのコマンドプロンプトではカレントディレクトリが表示される(os.getcwd()と同じ)がIPythonではホームディレクトリに戻ってしまうってことだな。
**B:** またややこしい…なんでまたそんなことに。
**A:** 私もよく知らないんだが、Unix系のシェルでカレントディレクトリを調べる場合はcdではなくpwdを使うからじゃないかな。 その証拠にIPythonでもpwdと入力するとカレントディレクトリが表示される。
**B:** ふうん。なるほど。
**A:** で、ここでも補完機能が威力を発揮する。途中まで入力してTab、と。
.. code-block:: ipythonconsole
In [8]: cd Do #TABキーを押す
Documents/ Downloads/
In [8]: cd Do
**B:** おお。便利便利。
**A:** ファイルの一覧が見たい時にはlsと入力する。Windowsコマンドプロンプトのdirみたいなものだ。 やはりこれもUnix系のシェルでファイル一覧を得る時にはlsというコマンドを用いることに対応している。
.. code-block:: ipythonconsole
In [8]: ls
ドライブ C のボリューム ラベルがありません。
ボリューム シリアル番号は XX00-XXXX です
C:\Users\A のディレクトリ
2010/04/19 20:19 .
2010/04/19 20:19 ..
2010/06/08 20:34 .matplotlib
2010/04/19 20:30 .pylint.d
2010/04/16 15:49 .qsci
2010/04/19 20:30 .spyder
2010/04/14 20:51 _ipython
2010/04/28 16:17 Contacts
2010/06/09 13:58 Desktop
2010/06/01 19:06 Documents
#以下省略
**B:** ふむふむ。でも、それにしてもちょっと分からなくなってきたぞ。 なんでcd Documentsとかは文字列を示す''が要らないんだろう。そもそも()が省略できるのはなんで?
**A:** ほう。なかなかいいところに気付いたな。 cdやlsはIPythonの **Magic function** という特別な関数なんだ。 さっきhelp()という関数を紹介したが、cdやlsはのでhelpコマンドは「そんなの知らない」と答える。
.. code-block:: ipythonconsole
In [9]: help(ls)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
C:\Users\A\ in ()
NameError: name 'ls' is not defined
**B:** へ? じゃあlsのヘルプは見られないんですか?
**A:** IPythonのヘルプコマンドである?を使うといい。
::
In [10]: ls?
Type: System alias
Base Class:
String Form: (0, 'dir /on')
Namespace: Alias
Length: 2
Docstring:
Alias to the system command:
dir /on
Class Docstring:
tuple() -> an empty tuple
tuple(sequence) -> tuple initialized from sequence's items
If the argument is a tuple, the return value is the same object.
**B:** むむむ。難しいなあ。
**A:** Magic functionは%から始まるので、 **プロンプトに%だけ入力してTabを押すと一覧が見られる** 。IPythonは標準の設定ではMagic functionの%を省略できるようになっていて、%cdというはコマンドはcdとだけ入力すればいい。 まあ詳しく説明すると長くなるからここではこの程度でやめとくけど、とにかくhelp()で駄目なら?で調べるとかいろいろやってみるといい。 cdの詳しい使い方なんかもcd?してみて。
**B:** は-い。
**A:** さて、ぱぱっと短く済ませるつもりだったのに、ずいぶん長くなってきたな。次はMagic functionのひとつ、runだ。
**B:** …
**A:** …
**B:** …。ん? Aさん、どうしました?
**A:** いや、「runというとBASICのアレですね?」という発言を一瞬期待したんだが、よく考えたらBくんはN88-BASICとかなんか知らんよな。ぶつぶつ。
**B:** ???
**A:** いや、おっさんの戯言だ。気にしないでくれ。IPythonではrunというコマンドを使ってスクリプトを読みこんで実行することができる。 以下のサンプルプログラムをダウンロードして、cdでダウンロードしたディレクトリへ移動してrun 10-1.pyと入力してみてくれ。一応解説しておくと、方向が2種類、コントラストが4種類の組み合わせの刺激を5回ずつランダムに提示するプログラムの一部で、12行目からのforループでcndから方向とコントラストの値を取り出している。実際には14行目以降で刺激を描画したりキー押しを判定したりするわけだな。
+ 行番号なしのソースファイルをダウンロード→ `10-1.py `_
.. literalinclude:: source/10-1.py
:language: python
:encoding: shift-jis
:linenos:
:lineno-match:
**B:** えーと、D:\\work\\pythonに保存。cd D:\\work\\python。run 10-1.pyっと。
.. code-block:: ipythonconsole
In [12]: run 10-1.py
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
D:\work\python\10-1.py in ()
11
12 for i in index:
---> 13 d,c = cnd[i]
14
15
IndexError: list index out of range
WARNING: Failure executing file: <10-1.py>
**B:** あれっ、なんだかエラーが表示されているんですが。
**A:** エラーが出るように作ったんだ。 13と書かれた行の左に--->って矢印がついてるだろ。13行目でIndexErrorというエラーが起きて止まったってことだ。 さて、ここからがIPythonの本領だ。さっき言ったwhosというコマンドを使ってごらん。
**B:** whos、と。
.. code-block:: ipythonconsole
In [13]: whos
Variable Type Data/Info
-------------------------------
c int 60
cnd list [['L', 20], ['L', 20], ['<...>0], ['R', 80], ['R', 80]]
contrast int 80
d str L
direction str R
i int 66
index list [13, 66, 35, 20, 49, 15, <...>6, 77, 41, 14, 3, 19, 45]
it int 4
random module Python25\lib\random.pyc'>
**A:** whosを実行すると、このように現在pythonが保持している変数やモジュールがずらっと表示される。 さらに重要なことに、 **runで実行したスクリプトが正常終了であれエラーであれ終了すると、その時点の変数の値などがこうやってすべて残っている** 。 今までは、エラーが起きた時にはエラーメッセージを読んで、なぜそんなエラーが起きたのか頭の中でプログラムの流れを追って考える必要があった。 もしくは、変数の値をprintで画面に出力したりwriteでファイルに書きだしたりしなきゃいけなかった。 IPythonなら、そんなことをしなくても変数に自由にアクセスすることができる。
**B:** へえ。そりゃ便利!
**A:** さて、このサンプルプログラムではさっき言ったように13行目のd,c=cond[i]で何か問題が起こったわけだ。 whosの出力でiの値を見ると、プログラムが停止した時にはi=66だった事がわかる。cndの長さは?
**B:** へ? えーと、directionが2種類、contrastが…
**A:** いやいや、そうじゃなくて。cndは消えずに残ってるんだから、普通にlen()を使って調べればいい。
**B:** ええと、じゃあこうですかね。カタカタ。
.. code-block:: ipythonconsole
In [14]: len(cnd)
Out[14]: 40
**B:** cndの長さは40ですかね。40しかないのに66番目にアクセスしようとしたからエラーになったのか。
**A:** 正解。単に値やリストの長さを調べるだけじゃなく、インタプリタで使えるすべての機能を使って作業することができるので、「反応時間が1000msecより長い試行を除いて処理するとどうなる?」とかデータを見ながらいろいろな処理を試してみることが出来る。
**B:** ふうん。ぼくならそういうのはExcelの方がやりやすいですけどねえ。
**A:** その辺の好みは人それぞれだな。私だってExcelを全く使わないわけじゃないが、セルを選択して貼り付けて…とかいう作業を何枚ものシートに対して繰り返さなきゃいけないような処理をExcelでするのは御免だ。 「VBAを使えば?」って言う人もいるけど、pythonで処理中のデータをわざわざExcelに持って行ってVBAを使うくらいならpythonで全部書いちゃうよ。 共同研究者のリクエストでどうしてもExcelを使わなきゃいけない時くらいだな。VBAを使うのは。
**B:** わがままですねえ。
**A:** 共同研究者に合わせてExcel使うって言ってんのにわがままとか言うか。とにかく、いいかげん長くなってきたんでそろそろ締めくくらないと。 最後にIPythonの問題点、ってほどでもないんだけど、私が **個人的に** あまり好きじゃない点を2点挙げておく。まず第一にエディタとの連携。
**B:** エディタとの連携?
**A:** そう。特に試行錯誤でデータを分析している時なんかに、ちょっとプログラムを書いて動作を確認して、またプログラムを書きなおして動作を確認、という具合にエディタとインタプリタの間を行ったり来たりすることがよくある。
**B:** ふむふむ。
**A:** IPythonにはeditというMagic functionがあって、editor ほげほげ.pyとしてエディタを呼び出して、編集を終了してエディタを閉じたら自動的に評価してくれる。
**B:** ふむふむ。で?
**A:** 呼び出されるエディタの設定方法、.bashrcとかを書いたことがある人なら何も問題ないと思うんだけど、このコーナーで想定しているユーザー層を考えると、詳しく説明しないといけない。 そんなの面倒くさいからやりたくない。
**B:** …。
**A:** それからeditでエディタを呼び出した後、終了するまでIPythonのインタプリタで作業できないのも困る。 実行したプログラムにエラーがあった時、エラーの行番号まで自動的に飛んでくれないのも面倒くさい。
**B:** …やっぱりわがまま以外の何物でもない気が。
**A:** 前回「何が快適かは人それぞれ」って言っただろ? 極端な話、IPythonはなくても実験プログラムも分析プログラムも書ける。でも、快適な環境で書いた方がずっと作業がはかどる。快適さを求めるのがわがままというんなら、むしろ **わがままでいい** んだよ。
**B:** はあ。なんかすごく力入ってますね。それで、他にもなにかあるんですか?
**A:** うむ。unicode文字列の扱いにちょっと問題がある。VisionEggで日本語を表示するにはUnicodeを使う必要があるんで、Unicodeの扱いに問題があるのはちょっとまずい。
**B:** unicodeの問題?
**A:** 例題0-1で説明したとおりに普通のpythonインタプリタを起動してみる。そして変数stimに…そうだな、 「財布に1500円入っている」というunicode文字列を代入してみよう。
**B:** Aさんの例文はお金か食い物に関するものばかりですよね。
**A:** うるさい。で、この変数stimに代入された文の文字数を調べるには、どうしたらいい?
**B:** ええと、len(stim)。
**A:** その通り。やってみると、13という値が返ってくる。これは正しいかな?
**B:** へ? 正しいんじゃないんですか?
**A:** ちゃんと数えて。
**B:** めんどうくさいなあ。1、2、3、…。13文字ですね。
.. figure:: img/10-2-06.png
普通のpythonインタプリタの場合
**A:** よし。さらにprint stimとしてみる。そうするとちゃんと代入した文が表示される。
**B:** されますね。それで?
**A:** 同じことをIPythonでやってみる。len(stim)、と。
**B:** あれ、22文字になってる?
**A:** そう。現在配布されているIPython(注:version 0.10)ではunicode文字列の長さをちゃんと返せないんだ。例題1-5で解説した「刺激文の文字数から画面上の刺激文の長さを計算する」といった方法が使えなくなる。 さらにprint stimとやるとエラーになって表示できない。
.. figure:: img/10-2-07.png
IPythonの場合
**B:** ありゃりゃ…。これは「わがまま」とか「ちょっとまずい」とかいう問題じゃ済まないと思いますが。
**A:** いや、実はrunで実行すれば、正常に実行することができるんだ。 ちゃんとprintすることもできるし、VisionEggで画面に刺激として提示することもできる。 しかし、IPython上で変数に文字列を入力したりするとこの問題に引っかかる。 きちんとこの問題を意識して使えばいいんで致命的な問題ではないけど、いちいち意識しなきゃならんのはやっぱり快適ではないんで「ちょっと問題が」と言わざるを得ない。
**B:** むむー。なかなかこれで万全!とはいかないもんですねえ。
**A:** そりゃ仕方ないね。ま、いずれにせよ、IPythonは多分Unix系のOSが好きだったり馴染んだりしている人が幸せになれる環境だと思う。 次回はどちらかというとMatlabなどの開発環境に慣れている人が幸せになれそうなspyderというのを紹介しよう。
追記
~~~~
**IPython 0.11では上記のUnicode文字列の問題が解決されました** 。下のスクリーンキャプチャはIPython 0.12のものですが、u'財布に1500円入っている'の長さが正しく13になりますし、print文も正常に動作します。 自信を持ってIPythonの使用をお勧めできます。
.. figure:: img/10-2-08.png