[Python]LightGBMを使おうとしたら、WinError126が出て困った話

2022/01/30に公開

タイトルにはPythonと付けたけど、ほぼWindowsのお話。

起きたこと

機械学習でもやってみるかーってVS Code入れて、Python用拡張機能入れて…
ただ、ちょっと僕の環境はVisual Studio 2019も入ってて、そっちのPython環境を汚したくないなって思ったんで、venvを作ってそこにpip install jupyterpip install lightgbmを行って環境を作りました。

さぁ、次はPythonのコード書いて実行をしたわけですけど、すぐに
「[WinError 126] 指定されたモジュールが見つかりません。」
で止まってしまいました。はい。
これの解決方法がこの記事の趣旨です。
具体的には以下のようなスタックトレースが出力されました。

Z:\TEMP\ipykernel_11536\4041817684.py in <module>
      1 import numpy as np
      2 import pandas as pd
----> 3 import lightgbm as lgb
      4 
      5 import warnings

d:\VSCode\Python\testj\.venv\lib\site-packages\lightgbm\__init__.py in <module>
      6 from pathlib import Path
      7 
----> 8 from .basic import Booster, Dataset, Sequence, register_logger
      9 from .callback import early_stopping, log_evaluation, print_evaluation, record_evaluation, reset_parameter
     10 from .engine import CVBooster, cv, train

d:\VSCode\Python\testj\.venv\lib\site-packages\lightgbm\basic.py in <module>
    108 
    109 
--> 110 _LIB = _load_lib()
    111 
    112 

d:\VSCode\Python\testj\.venv\lib\site-packages\lightgbm\basic.py in _load_lib()
     99     if len(lib_path) == 0:
    100         return None
--> 101     lib = ctypes.cdll.LoadLibrary(lib_path[0])
    102     lib.LGBM_GetLastError.restype = ctypes.c_char_p
    103     callback = ctypes.CFUNCTYPE(None, ctypes.c_char_p)

C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\ctypes\__init__.py in LoadLibrary(self, name)
    440 
    441     def LoadLibrary(self, name):
--> 442         return self._dlltype(name)
    443 
    444 cdll = LibraryLoader(CDLL)

C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\ctypes\__init__.py in __init__(self, name, mode, handle, use_errno, use_last_error)
    362 
    363         if handle is None:
--> 364             self._handle = _dlopen(self._name, mode)
    365         else:
    366             self._handle = handle

OSError: [WinError 126] 指定されたモジュールが見つかりません。

環境

  • Windows 7 64bit
  • Visual Studio Code
    • Python 3.7.5
    • venv
    • Jupyter Notebook
    • LightGBM

エラーの原因

結論から言うと、pip install lightgbmでインストールされたlib_lightgbm.dllの動作に必要な依存関係のDLLが、僕のマシンに無いので出てます。

解決方法

どうやらpip installで入れたLightGBMは「Microsoft Visual C++ 2015 再頒布可能パッケージ」が動作に必要なんですね。(2022年1月時点)

方法A 「Microsoft Visual C++ 2015 再頒布可能パッケージ」をインストールする

よって、Microsoftダウンロードセンターへ行き、上記のパッケージを検索して出てきたやつをインストールしましょう。(32bit用と64bit用がありますが、この際両方入れておいていいです。)
これで問題が解決したなら方法Bはやらなくてかまいません。

方法B LightGBMのGitHubへ行き、別のlib_lightgbm.dllをダウンロードして入れ替える

まあ、上記の方法で解決するならわざわざ記事は作らなかったんですが、たまたま僕のマシンはVisual Studio 2019等々が入っていたため、「Visual Studio 2015、2017、2019 用 Microsoft Visual C++ 再頒布可能パッケージ」が既にインストールされていました。
すると、なんと「Microsoft Visual C++ 2015 再頒布可能パッケージ」はインストールできません。(じゃあ、何でDLL足りねーんだよ!)

その場合は、GitHubのLightGBMのページへ行き、右側にあるReleasesページへ飛んで、lib_lightgbm.dllをダウンロードしましょう。おっと、pip installで入れたバージョンと同じやつにしましょう。忘れた場合はpip listで見れます。

後は先ほどのスタックトレースで表示されたLightGBMのインストール場所に行くと、lib_lightgbm.dllがあるので、ダウンロードしてきたDLLと入れ替えます。

僕の場合は以下の場所になります。
d:\VSCode\Python\testj\.venv\lib\site-packages\lightgbm\

終わり

いかがでしたか?エラーは出なくなったでしょうか?
まあ世の中どんぴしゃの同じ原因もあれば、ちょっと自分の問題とは違うな…なんてことありますよね。
だから、この先に付録としてエラーを解決するために行った調査の軌跡を載せておきます。

付録1 最初に調べること

まずはエラーの文言でググりますよね「lightgbm WinError 126」などで検索しました。
すると、stackoverflowで同じようなエラーで困っている人がいました。解決策は「vcomp140.dllを入れろ」と…こういう時、vcomp140.dllへのLinkが貼られていますが、素性の知れないDLLをダウンロードして入れるのは止めましょう。(ダメ、絶対)
vcomp140.dllについて調べてみると、「Microsoft Visual C++ 2015 再頒布可能パッケージ」の一部だとわかりました。

ただ、僕の場合は「もう入れてあったような気がするけど…」と思うわけですが、一応確認しました。

  • コントロールパネルを開き、「プログラムと機能」からインストールされているソフトの一覧を表示して確認しました。
    →あった。ちょっと名前は「2015-2019 再頒布可能パッケージ」になっているけど。
  • 同時にC\Windows以下を「vcomp140.dll」で検索しました。
    →あった。(system32以下に1つ、SysWOW64以下に1つ。つまり、32bit用と64bit用です)

付録2 環境変数PATHの確認

どうやら「DLLはあるけど動かない」雰囲気がしますね。
なので次は環境変数PATHの確認をしました。確かに、実行環境はvenvの仮想環境下にあり、Jupyter Notebookです。もしかしたら、上手くWindowsのDLLを探せてないのかもしれません。

次のコードを問題のエラーが出るコードの先頭に追加するか、別のJupyterのセルに書き実行しました。

import os
print(os.getenv('PATH'))

すると、以下を得ました。

d:\VSCode\Python\testj\.venv\lib\site-packages\pywin32_system32;D:\VSCode\Python\testj\.venv\lib\site-packages\pywin32_system32;D:\VSCode\Python\testj\.venv\Scripts;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\dotnet\;d:\VSCode\Python\testj\.venv\lib\site-packages\numpy\.libs;d:\VSCode\Python\testj\.venv\lib\site-packages\scipy\.libs

横にクソ長くてすいません。でもこれは僕のマシンの結果なので、詳しく見る必要はないです。
それで、先ほど調べたvcomp140.dllの場所「C:\Windows\system32」が上記に含まれているか、確認しました。
→あった。

付録3 lib_lightgbm.dllの依存関係を調べる

どうやら、環境変数に問題はないようです。でも、動きません。
さらに情報を集めるうちに、LightGBMの本体は「lib_lightgbm.dll」というDLLだとわかりました。
確かに、venvがある場所を検索するとlib_lightgbm.dllがありました。

なるほど、こいつが動かないのか?
であれば、DependenciesというソフトでDLLの依存関係を調べましょう。GitHubのDependenciesのページ
DependenciesGui.exeを起動し、問題のlib_lightgbm.dllをD&Dします。
すると、?マークが付いたDLLが(たまたま僕のマシンでは2つ)ありました。

  • api-ms-win-core-winrt-l1-1-0.dll
  • api-ms-win-core-winrt-string-l1-1-0.dll

おっ、足りないDLLがはっきりしたようですね。vcomp140.dllも必要だと表示されていますが、それはあるので?マークは付いていません。
足りない2つのDLLについて調べてみると、どちらも「Microsoft Visual C++ 2015 再頒布可能パッケージ」に含まれるようです。
「堂々巡りやめろ!!」
また、同じ原因に戻って来ちゃったわけですが、「api-ms-win-core-winrt-l1-1-0.dll」を僕のマシンで探してみると、確かにありません。とすると、少なくとも動かない原因ははっきりしました。

付録4 2015年って古くないか?

lib_lightgbm.dllに必要なDLLが無いから動かない。
でも、必要なDLLちょっと古くないか?もっと、最新のビルドであれば「Microsoft Visual C++ 2015 再頒布可能パッケージ」を要求してこないのでは?ということに気づき、調査中に見つけたGitHubのLightGBMのページを思い出したわけです。

そこにあるlib_lightgbm.dllの依存関係を調べると、上記の2つのDLLは必要なくなっています。他に?マークもありません。これはもしかして…動く?
こうして見つかったのが方法Bでした。いやー参ったね。
なんで「Microsoft Visual C++ 2015 再頒布可能パッケージ」にあったファイルが、
「Visual Studio 2015、2017、2019 用 Microsoft Visual C++ 再頒布可能パッケージ」に無いのか…

まあ僕の環境が変だったというオチかもしれません。
この記事が誰かの助けになればと思って書きました。

Discussion