どうせ和布蕪るなら、の続き、にちゃんとなりそう (ライブラリとしての利用?)

悔しさ余って憎さ1倍

アゲイン、あんどなでじゃーぶ。


Mecab-python、natto-py に失敗した話、の続きというか。

  • natto-py など、すぐに手に入るヤツが Windows で全滅だった
  • mecab 公式のレポジトリにある python バインディングが保守されてない
  • 幸いmecab 公式のpython バインディングは(素の) swig なので

「生成し直しちゃいなよ」、まる。

mecab 公式レポジトリにある「swig による生成物」は、古い swig と古い python (2.6 以下)によるものなのだが、インターフェイス(*.i)の仕様が変わってないんであれば、「新しい swig で」生成し直せば、望みの python 用になるであろう、と。

これも幸いというかなんというか、mecab 公式レポジトリにある「swig による生成物、をインストールするための setup.py」はほんっと最小限のことしかしてないんで、自力で全部書き下してしまったほうが早いと思われる。

つーわけで。

さて、swig は確か前に持ってきてたよなぁ…、と探すも、見つからない。うーん、かなり前だからなぁ、もしかして、今の PC の前のヤツだった頃か? とすりゃ、もう6年以上前だわ。なので http://www.swig.org/download.html より swigwin-4.0.1 をダウンロード。「インストール」の公式な方法ってのはなさげね。バイナリ一個をぺろっと好きな場所に置くだけ、か。

んで、必要なのは「mecab のソースパッケージ」ね。GitHub からか 公式ドキュメント のどっちからでもいいけど、それの mecab/swig が目的のもの。

 1 [me@host: mecab-0.996]$ mkdir python
 2 [me@host: mecab-0.996]$ cd swig
 3 [me@host: swig]$ make SWIG=../../swigwin-4.0.1/swig.exe python
 4 c:/Users/hhsprings/swigwin-4.0.1/swig.exe -python -shadow -c++ MeCab.i
 5 ..\src\mecab.h(136) : Warning 302: Identifier 'surface' redefined by %extend (ignored),
 6 MeCab.i(74) : Warning 302: %extend definition of 'surface'.
 7 ..\src\mecab.h(848) : Warning 302: Identifier 'set_sentence' redefined by %extend (ignored),
 8 MeCab.i(95) : Warning 302: %extend definition of 'set_sentence'.
 9 mv -f MeCab_wrap.cxx ../python
10 mv -f MeCab.py ../python
11 [me@host: swig]$ ls -lh ../python
12 total 277K
13 -rw-r--r-- 1 hhsprings Administrators  13K Nov 20 21:05 MeCab.py
14 -rw-r--r-- 1 hhsprings Administrators 264K Nov 20 21:05 MeCab_wrap.cxx

とここまでが、前回の「失敗談の前置き」。

「「MeCab 自身の 64bit 対応が出来てないので、CPython amd64 版は(MeCab 自身の改変なしでは)不可能」」はガセだった。しっかり「HAVE_UNSIGNED_LONG_LONG_INT」で措置されていた。

というわけで、こんな setup.py を書けばビルド出来る:

Windows な CPython 3.5 なことしか踏まえてないのがアレだ
 1 # -*- coding: utf-8 -*-
 2 import re
 3 from distutils.core import setup, Extension
 4 
 5 
 6 _OBJS = """feature_index.obj param.obj  learner.obj string_buffer.obj \
 7 	char_property.obj         learner_tagger.obj    tagger.obj \
 8 	connector.obj             tokenizer.obj \
 9 	context_id.obj            dictionary.obj  utils.obj \
10 	dictionary_compiler.obj   viterbi.obj \
11 	dictionary_generator.obj  writer.obj iconv_utils.obj \
12 	dictionary_rewriter.obj   lbfgs.obj eval.obj nbest_generator.obj"""
13 _SRCS = ["../src/{}".format(obj.replace(".obj", ".cpp"))
14          for obj in re.split(r"\s+", _OBJS)] + ["../src/libmecab.cpp"]
15 setup(
16     name="mecab-python",
17     version="0.996",
18     py_modules=["MeCab"],
19     ext_modules=[
20         Extension(
21             "_MeCab",
22             _SRCS + ["MeCab_wrap.cxx",],
23             extra_compile_args=[
24                 # "-GA", "-Zi",
25                 "-wd4800", "-wd4305", "-wd4244",
26                 "-wd4267",
27                 ],
28             define_macros=[
29                 ("HAVE_STDINT_H", "1"),
30                 ("_CRT_SECURE_NO_WARNINGS", "1"),
31                 ("_CRT_SECURE_NO_DEPRECATE", "1"),
32                 ("HAVE_UNSIGNED_LONG_LONG_INT", "1"),
33                 ("MECAB_USE_THREAD", "1"),
34                 ("HAVE_GETENV", "1"),
35                 ("HAVE_WINDOWS_H", "1"),
36                 ("DIC_VERSION", '102',),
37                 ("VERSION", '"\\"0.996\\""'),
38                 ("PACKAGE", '"\\"mecab\\""'),
39                 ("UNICODE", "1"),
40                 ("_UNICODE", "1"),
41                 ("MECAB_DEFAULT_RC", '"\\"c:/Program\\032Files\\032(x86)/MeCab/etc/mecabrc\\""'),
42                 ],
43             undef_macros=[
44                 "DLL_EXPORT",
45                 ],
46             include_dirs=["../src"],
47             library_dirs=["../src"],
48             libraries=["advapi32"],
49             )
50         ])

まだ「ビルド出来た、あーんど、インストールしてモジュールインポートまではうまくいった」が出来ただけなので、何にも保障はしないけれど、ともあれ前進は前進。あと、前回書いた通りこれは「抱え込み」なので、仮に MeCab 公式のバージョンアップがあって libmecab.dll が更新されたとしてもそこから置いてけぼりになることには注意。

あと、Python 2.7 用のは…、興味ある? 欲しい? ワタシはいらんなぁ。いくら「Python 2.7 を 2025 年までは見捨てない」と言ったからといって、さすがに C 拡張を伴うものまではやってらんない。挙げた setup.py のままで行ければ行けるだろうし、行けなきゃいけない。というか少なくとも stdint.h はないので、HAVE_STDINT_H は外さないとダメだろうね。外すだけで行けるかもしれん。どうかな。やってはみないけど、どうしてもという人は、是非奈落に落ちてみればいいと思う。

にしても、作ったはいいが、使い方がまったくわからん。natto-py から使い方を探るしかないかなぁ。