2007年12月12日

WindowsのPython用MeCabパッケージを作って、それに対応してみた。

前回の日本語を音素に分解するスクリプトの公開で、Ctypesを利用してMeCabを操作していたのは、Python用MeCabモジュールのWindows版作れなかったから。せっかく公式モジュールがあるのだから今回はこれを使えるようにしてみた。普通に、MeCabサイトからPython用のバインドモジュールをダウンロードできるが、インストールしようとするとコンパイラとしてVC++2003を要求されてしまう。物持ちがよくて現役を退いたVC++2003を用意できたとしても、今度はコンパイルエラーが出てしまう。

理由を調べてみると、「MeCabのPythonバインディングをWindowsでビルド」に書いてあった。MeCab.hを次の差分のように書き換えなくてはいけない。上記のリンク先の変更とは多少違う。
--- mecab.h.original
+++ mecab.h
@@ -216,12 +216,12 @@

virtual ~Tagger() {}

-#ifndef SIWG
+#ifndef SWIG
static Tagger* create(int argc, char **argv);
static Tagger* create(const char *arg);
-#endif

static const char *version();
+#endif
};

/* factory method */


MeCabサイトに行ってソースを持ってきて解凍し、srcフォルダに入っているMeCab.hを上記のように書き換え、SWIGを使ってmecab_wrap.cxxを作り直す。SWIGというのは、バインドのためのコードを自動で作ってくれるソフト。MeCabの公式のPythonバインドもこれを使って生成されている。SWIGサイトからWindows版を持ってきてインストールするmecabソースのswigフォルダで下記のようなコマンドを実行すると、i拡張子のファイルの指示に従って、仲介するコードを作ってくれる。
swig -python -c++ -o mecab_wrap.cxx mecab.i

なおこのswig.exeにはPATHは通っている。以後上記のようなコマンドの例は適切にPATHなどの環境変数が設定されているとする。

そして、「Windows で MeCab python binding をコンパイルする (2006/01/15)」を参考にして、setup.pyも修正する。MeCabのWindows版が標準の場所「C:/Program Files/MeCab/sdk」にインストールされているとすると、次のようになる。
setup(name = "mecab-python",
version = '0.96',
py_modules=["MeCab"],
ext_modules = [
Extension("_MeCab",
["MeCab_wrap.cxx",],
include_dirs=['C:/Program Files/MeCab/sdk'],
library_dirs=['C:/Program Files/MeCab/sdk'],
libraries=['libmecab'])])


このフォルダで次のコマンドを実行するとセットアップが完了する(VC++2003を持っていれば)。
python setup.py install


さて、VC++2003(VC7.1)が要求されるのはどうしてだろう。それはWindows向けのPython2.5がVC++2003でコンパイルされて作られたプログラムだからだ。もっと詳しく言うとPython2.5がMSVCR71.DLLを使っているから。Windowsではコンパイラの種類によって、それで作ったプログラムの使うMSVCRTの種類が違ってくる。そしてその違うMSVCRTを一つのプログラムの中で使おうとすると、ランタイムエラーでプログラムが止まってしまう。Pythonのセットアップスクリプトは、Python本体を作るときに利用したのと同じVC++2003を要求して、モジュールでも同じMSVCR71.DLLを使おうとする。

VC++2003を持っていると、とりあえず上記の改造されたMeCab.hを使って作ったmecab_wrap.cxxをsetup.pyでコンパイルしインストールができる。では持っていない人はどうすればコンパイルできるだろうか。残念ながらVC++2003は販売終了している。同じランタイムでコンパイルしてくれるものに、Visual C++ Toolkit 2003というコンパイラがある。これは数年前までマイクロソフトから無料で配布されていたコンパイラだ。一緒にPlatform SDKをインストールして使う。そのままではsetup.pyでコンパイルできないが、setupを解釈するスクリプトを改造(Python 2.4 Extensions w/ the MS Toolkit Compiler参照)すれば、パッケージを作ってくれる。残念ながらこのVC++ToolKit2003も配布は終了している。

そういうわけで現在ではMSVCRT7.1を使うマイクロソフト純正コンパイラは入手困難となっている。それでも、どうしても入手しなくてはいけないのならば、マイクロソフト社のMSDNに入会することになるだろう。旧バージョンの使用 (ダウングレード) - MSDN。タイムリーにもMSDNへは現在VC++2008発売直前のキャンペーンで少し安く入会できる。 Visual Studio 2008 早期導入キャンペーン 。もう一つ、特定のバージョンを以前買ったことがある人へのキャンペーンも実施されている。Visual Studio 2008 早期導入キャンペーン 〜今なら更新パッケージがお得!〜。でもどちらにしても、仕事で使わない限り、手軽に買える商品ではないので、これは万人の解決法ではない。

ではどうするかというと、MSVCR71.DLLを使うことを諦めて現在入手可能なコンパイラを使ってMSVCRTそのものを使わないモジュールを作ればいい。その組み合わせで問題が起きないかはやってみないと分からないが。Visual C++ 2005 Express Edition 日本語版(VC8)は登録が必要だが無料で入手できる。これもPlatform SDKをインストールして使う。(Visual C++ 2005 Express Edition と Microsoft Platform SDK を一緒に使うを参照)。このコンパイラでも上で作り直したmecab_wrap.cxxをそのままコンパイルすることができる。そのときコンパイラのスイッチとして、/MDではなく/LDを使う(/MTでも良さそうだが今回/MTで動かなかった)。/LDだとMSVCRTを使わないDLLを作る。とりあえずこれで動く。
cl -EHsc /LD /Ox /I "c:\Program Files\MeCab\sdk"
/I "C:\Python25\include" mecab_wrap.cxx
"C:\Program Files\MeCab\sdk\libmecab.lib"
"C:\Python25\libs\python25.lib"
長いので折り曲げて書いてあるが上記を一行で書く。環境変数path、include、libが適切に設定されているとする。上記「MeCabのPythonバインディングをWindowsでビルド」にあるものと同じコード。

でも、誰かがコンパイルしたものを配ってくれれば個々にこんな面倒なことをしなくてもいい。それもMSVCR71.dllに対応したコンパイル済みのモジュールを。MeCabの配布先でついでに公開してもらえると楽なんだけどまだそれはない。調べてみると、setup.pyスクリプトでモジュールのインストールができると、ほんの少しのコマンドラインの変更で配布用パッケージも作ることができるのが分かった。pyhtonにはこのようにパッケージを作る機能も備わっている。いろんな所で見かけたpythonの配布パッケージもそうやって作っていたのかと今回初めて知った。

長々と書いてきたけれど、そういうわけで、setup.pyを使って作ってみた。自己責任でご利用を。
ダウンロード mecab-python-0.96.win32-py2.5.exe

そして、このMeCabモジュールを利用してスッキリした記述にしたpyDaTTL0.6
ダウンロード pyDaTTL06.zip

上記のプログラムを利用するためには、libmecab.dllへPATHが通っていないといけない。手っ取り早い方法は、"C:/Program Files/Mecab/bin"にあるlibmecab.dllを確実にPATHが通っている"C:/WINDOWS/SYSTEM32/"に放り込めばいい。けれど、MeCabを使っていろいろ試してみるにはこのbinフォルダにある他のコマンドが自由に使えた方が楽なので、今後のためにこのbinフォルダをPATHに追加しておいてもいい。


拍手する
posted by takayan at 01:20 | Comment(0) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]


この記事へのトラックバック