環境
ubuntu 14.04
cabocha 0.69
cabocha-python 0.69
問題の概要
変な挙動だった。というか率直に言ってバグなのでは?
>>> import CaboCha >>> cparser = CaboCha.Parser() >>> tree1 = cparser.parse("吾輩は猫である。") >>> print(tree1.toString(CaboCha.FORMAT_TREE)) 吾輩は-D 猫である。 EOS >>> tree2 = cparser.parse("吾輩は猫ではない。") >>> print(tree1.toString(CaboCha.FORMAT_TREE)) 吾輩は-D 猫ではない。 EOS
これはおかしい。CaboChaはこわれている。
いや、「これで仕様通り動いてる。おまえの使い方が間違ってるんだ」て言われたら反論できないけど。詳細なドキュメントを見かけたことがないので、もしかしたらアホなこと(Parserのインスタンスの使い回し)をやっているのかもしれない。
回避するために試したこと
- CaboCha.Parser("")する(コンストラクタに空文字列を渡す)
効果なし。
- 一度空文字列に対してparseを呼ぶ
ここを参考に「もしかしたら効くかも」と思ってやってみた。
MeCabのparseToNodeのひどいバグ - 北野坂備忘録
効果なし。
- 文字列を変数に入れる、encodeする
ここを参考に(以下略)。
MeCabをPythonから使う注意点とか
効果なし。encodeに至ってはやったら落ちた。
- 仕方がないのでCaboCha.Parser()を毎回作る
>>> tree = CaboCha.Parser().parse("吾輩は猫である。")
>>> tree.toString(CaboCha.FORMAT_TREE)
Segmentation fault (コアダンプ)
たぶん本体のメモリ管理とpythonの接合が上手く行っていないのだろうけど、さて困った。
>>> parser1 = CaboCha.Parser() >>> parser2 = CaboCha.Parser() >>> tree1 = parser1.parse("吾輩は猫である。") >>> tree2 = parser2.parse("吾輩は猫ではない。") >>> tree1.toString(CaboCha.FORMAT_TREE) ' 吾輩は-D\n 猫である。\nEOS\n'
一応回避できることはわかった。これで書くと極めて非python的なプログラミングを強いられるという問題はあるが、たぶんなんとかなる。
ちなみに、ParserのインスタンスがGCに回収されると treeだけ残っててもtoStringできないようです(Segmentation faultを吐いてくれる)。どんな作りになってるのかなんとなくわかってきたけど、率直に言って○○。
def parse(sentences): """ sentencesは一文ずつに区切られた文のリストとして扱う """ trees = [] plist = [] for s in sentences: parser = CaboCha.Parser() trees.append(parser.parse(s)) plist.append(parser)
このようなものを書いてあげれば、後からtreeを使うことができることがわかった。率直に言ってまったく嬉しくない。
問題原因の切り分け
は、できてないです。
- うちの環境固有の問題
- cabocha-pythonの特定のバージョンの問題
- cabocha-python固有の問題
- cabocha固有の問題
とりあえず逃げれることはわかったので、僕はやらない(明言)。
対策
たぶん解析結果のtreeオブジェクトを使いまわそうという発想が間違っていて、cabochaのtreeオブジェクトを使わないで初手でXMLか何かに変換して取り扱うのが楽だと思います。そんなことを強いるバインディングって何よ? って気がしますが。
もう面倒くさいから、JUMAN/KNPに鞍替えしようかなと思う今日この頃。