ipython布教活動

細かいことは気にせず、

ipythonを使うべし。

IPython

f:id:kimoppy126:20180828232504p:plain

IPythonは、対話的コンピューティングと、並列コンピューティングを行うためのオープンソースプラットフォームです。
機能をご紹介しましょう。

補完機能

pythonインタプリタでTab補完機能を使うことができます。 説明不要ですね。

イントロスぺクション

object_name? のように、オブジェクト名に?を付けて実行すると、そのオブジェクトの情報が表示されます。

ex)

In [13]: test = [1, 2, 3, 4]

In [14]: test?
Type:        list
String form: [1, 2, 3, 4]
Length:      4
Docstring:
list() -> new empty list
list(iterable) -> new list initialized from iterable's items

入出力履歴の保存

直近の3つの出力は、_, __, ___ という名前で保存されています。

ex)

In [26]: 1 + 2 + 3
Out[26]: 6

In [27]: _
Out[27]: 6

マジックコマンド

  • 行に対して適用→ ラインマジック
    頭に%のついたコマンドで、以降のその1行の内容を引数としてコマンドに渡します。
  • セルに対して適用→セルマジック
    頭に%%のついたコマンドで、その行だけでなく、複数行を渡すことができます。

マジックコマンドはデコレートするだけで拡張を作れたりもします。

ex) %timeitは、複数回の計測を行って、その平均が出力されます。

In [8]: %timeit list1 = [1, 2, 3, 4] * 1000
8.1 µs ± 465 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%%writefileは、テキストファイルを生成できます。
簡単なスクリプトを作成したい際に便利。

例えば、、

In [11]: %%writefile test.py
    ...: for i in [1, 2, 3, 4]:
    ...:     print(i)
    ...:
Writing test.py

test.pyが以下のように作られているはずです。

for i in [1, 2, 3, 4]:
    print(i)

因みに?をつければマジックコマンドのドキュメントを参照することができます。

In [22]: %%writefile?
Docstring:
::

  %writefile [-a] filename

Write the contents of the cell to a file.

The file will be overwritten unless the -a (--append) flag is specified.

positional arguments:
  filename      file to write

optional arguments:
  -a, --append  Append contents of the cell to an existing file. The file will
                be created if it does not exist.
File:      ~/.pyenv/versions/3.6.5/lib/python3.6/site-packages/IPython/core/magics/osm.py

ソースコードは??を付ければ見れます。

%timeit??
Source:
    @skip_doctest
    @line_cell_magic
    @needs_local_scope
    def timeit(self, line='', cell=None, local_ns=None):
        """Time execution of a Python statement or expression

        Usage, in line mode:
          %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
        or in cell mode:
          %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
          code
          code...

        Time execution of a Python statement or expression using the timeit
        module.  This function can be used both as a line and cell magic:

        - In line mode you can time a single-line statement (though multiple
          ones can be chained with using semicolons).

シェルの使用

シェルのコマンドをpythonインタプリタから使用することができます。
→pythonのオブジェクトにシェル関数の実行結果を代入することができます。

ちなみに、主要なシェルコマンドは ! を付けなくてもシェルで実行できます。

ex)

files = !ls

デバッグ

ipythonではpdbのラッパー的な使い方ができます。

以下の関数を用いて、デバッガの使い方を見ていきましょう。
test = 1 + 1なんのためにやってんの??って質問はしないでください。
デバッグモードのコマンドについても、このあたりに説明を譲ります。

def test_zero_division():
    test = 1 + 1
    value = 5/0
    return value

検死モード

1

エラー発生時にデバッガを起動したい場合を見ていきます。
いざ、実行!

In [18]: test_zero_division()
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-18-8ba600e9545b> in <module>()
----> 1 test_zero_division()

<ipython-input-17-ab1fd07ee841> in test_zero_division()
      1 def test_zero_division():
      2     test = 1 + 1
----> 3     value = 5/0
      4     return value

ZeroDivisionError: division by zero

上記のエラーで止まったとする。ここで、%debug

In [19]: %debug
> <ipython-input-17-ab1fd07ee841>(3)test_zero_division()
      1 def test_zero_division():
      2     test = 1 + 1
----> 3     value = 5/0
      4     return value

ipdb>

エラーが出るvalue = 5/0 にbreakpointが設置されています。

エラーの出た箇所でデバッグモードを起動することができるのです。

2

%pdb on

を実行しておけば、エラー発生時に自動でデバッグモード突入します。
つまり%debugを打つ必要がなくなります。

ステップモード

1

次に、ステップモードでのデバッガを見ていきましょう。
その名の通り、ステップごと(1行ごと)に実行していくデバッグ方式です。

まず、デバッグしたい行の前に以下を追加します。

from IPython.core.debugger import Pdb; Pdb().set_trace()

上記の関数を使うと、こんな感じ。

def test_zero_division():
    from IPython.core.debugger import Pdb; Pdb().set_trace()
    test = 1 + 1
    value = 5/0
    return value

実行してみましょう。

In [16]: test_zero_division()
> <ipython-input-14-cf5536426523>(3)test_zero_division()
      1 def test_zero_division():
      2     from IPython.core.debugger import Pdb; Pdb().set_trace()
----> 3     test = 1 + 1
      4     value = 5/0
      5     return value

n で1行先に進みます。

ipdb> n
> <ipython-input-14-cf5536426523>(4)test_zero_division()
      1 def test_zero_division():
      2     from IPython.core.debugger import Pdb; Pdb().set_trace()
      3     test = 1 + 1
----> 4     value = 5/0
      5     return value

再度nを入力。

ipdb> n
ZeroDivisionError: division by zero
> <ipython-input-14-cf5536426523>(4)test_zero_division()
      1 def test_zero_division():
      2     from IPython.core.debugger import Pdb; Pdb().set_trace()
      3     test = 1 + 1
----> 4     value = 5/0
      5     return value

見事ZeroDivisionErrorが出ました。

こんな感じです。慎重派のあなたにぴったりです。

ipythonを使ったワークフロー

REPL (Read Eval Print Loop) に従います。

  1. お好きなターミナルを開きます。作業ディレクトリまで行き、エディタ を開きます。
  2. お好きなターミナルを開きます。作業ディレクトリまで行き、ipythonを起動します。
  3. Let's coding!
  4.  %run myscript.py
    

    で実行します。

このワークフローであれば、お好きなエディタを使って編集しながら対話的に実行することができちゃいます。

※ 注意 myscript.py中で別の変更中のモジュールをimportしている場合、deep reloadしないといけません。

import reload
from IPython.lib.deepreload import reload as dreload
dreload(myscript)

また、imp.reload(my_module)を実行しておけば、指定したモジュールが自動でreloadされます。