回心誌

日々是回心

【cython、IPython】IPythonでpyx更新時に一々抜けなくても済む方法

IPython上でpyximportを使うと、pyxファイルをimportすることができる。嬉しいことに、その場でコンパイルまでしてくれる。

ただ、importした状態でpyxファイルを書き換えても、直ちに反映されるわけではなく、通常は一度IPythonを終了して再起動する必要がある。(O'REILLYのCython本にも度々そういう箇所があるが、一度IPythonを終了するよう記述がある)

非常に面倒臭かったが、一々抜けなくても良い方法がある。

reload_support=Trueを引数に与えてpyximport.installを呼び出せば良い。

import pyximport
pyximport.install(reload_support=True)
import hogepyx

これでhogepyx.pyxを変更した際には

reload(hogepyx)

とすれば、再度コンパイルが走る。

こんなに便利なのにCython本に載ってないのはどういうわけだろう。機能追加が最近だったのか、実は推奨していない理由があるのか。


IPythonを開く際に自動でpyximportが動くようにしてしまうと都合が良い。
シェル上で

ipython profile create cython

するとコンフィグファイルのパスが表示されるので、そのファイルを開き、
開いたファイルに以下の4行を付け加える

c.InteractiveShellApp.exec_lines = [
    'import pyximport',
    'pyximport.install(reload_support=True)'
]

IPythonを立ち上げる際に

ipython --profile=cython

とすれば、立ち上がる際にpyximportがimport、installされる。

Cython ―Cとの融合によるPythonの高速化

Cython ―Cとの融合によるPythonの高速化

【cython】pxdでstruct宣言するときに Variable type 'hoge' is incompleteってでた時どうするか。

structの宣言でハマった。

こういうstructを作りたい時。

#filename: test1.pyx
cdef struct XY:
    int x,y
def method():
  ......
#filename: test1.pxd
ctypedef struct XY

こんな感じに書いてた。

そうすると、実際にcimportして構造体を使うときに怒られる。

#filename test2.pyx
from test1 cimport XY
def functest():
    cdef XY xy

こんな感じに↓

cythonize test2.pyx
...
中略
...
test2.pyx:4:12: Variable type 'XY' is incomplete


pyx, pxdをこう書き換える必要がある。pyxからpxdに、構造体の宣言を書き写せばいい。

#filename: test1.pyx
def method():
  ......
#filename: test1.pxd
ctypedef struct XY:
    int x,y


ちなみにO'REILLYのCython本には

simulator.pxdに含まれている宣言を、実装ファイルにも書くことはできない。書くと、コンパイルエラーが発生する。

とあり、pxdとpyxに同じ宣言を書けないような記述があるが、実際にやってみてもコンパイルエラーにはならなかった。structは別とか、矛盾がなければスルーするとか、そういう感じなのかな。

こういうことで一々ハマるし、ググっても答えにたどり着けないので大変だ。