経緯

Jupyter Notebook の Python 3 Kernel で Cython を使う際、Cython 部分のソースコードを書き換えた後、再度実行させても変更が反映されていないことがあると気づきました。

例えば以下の notebook を考えます。このままだと正常に動いています。

In [1]: %reload_ext Cython
In [2]: %%cython --name foobar            
        def f(int a, int b):
            return a + b    
In [3]: f(5, 3)
Out[3]: 8

ここで、return a + breturn a - b に変更して再度走らせてみます。すると、本来は 2 と出力して欲しいところ、元のまま 8 が出力されます。

In [1]: %reload_ext Cython
In [4]: %%cython --name foobar            
        def f(int a, int b):
            return a - b    
In [5]: f(5, 3)
Out[5]: 8

奇妙なのでいくつか設定を変えて試してみた所、以下のことが分かりました。

  • Kernel ごと restart して最初から走らせると、更新が反映されて 2 が出力される。
  • Cython magic から --name / -n オプションを消して %%cython のみにすると、kernel の再起動無しに変更が反映される。
  • Cython magic に --force を指定しても挙動は変わらない。
  • Cython 関係なく IPython ではモジュールが再読込されないことが問題なのかと思い、"Reloading submodules in IPython" に従って以下の行を最初のセルに追加し再度試してみたが、挙動は変わらなかった。

    %load_ext autoreload
    %autoreload 2
    

質問

Cython 部分のコードを変更するたびに kernel を再起動するのは面倒です。ひとまず --name の指定を外せば更新が反映されることは分かったので今はそうしていますが、--name を付けたまま更新を逐次反映させる便利な方法は無いのでしょうか? カーネルを再起動する以外の方法があれば、ご教示ください。

環境

  • Jupyter Notebook 5.4.0 + Python 3 Kernel
  • Python 3.6.4 :: Anaconda custom (64-bit)
  • Ubuntu 18.04 Bionic