LoginSignup
6
4

[Python3.7] windows10上の Jupyter Notebook で Cython を動かそうとしたら "DistutilsPlatformError: Unable to find vcvarsall.bat"

Last updated at Posted at 2019-09-08

Summary

windows10にpythonをインストールし、Jupyter NotebookでCythonの力を試そうとしたところ、DistutilsPlatformError: Unable to find vcvarsall.batというエラーに遭遇。

  • 初回: 対処に4時間かかったorz
  • 4年後: 対処に1.5日かかった..._(⌒(_´-ω-)_

でも!対処できたので記録を残しておこうと思います。

多分、この記事が参考になるという人はほとんどいないのではないかと思います....(危険な方法のため。もし、他の方法があったら是非教えて下さい)

環境1

4年前にこの問題に出くわした時の環境。

- version
windows 10
Visual Studio Express Edition 2017
Anaconda3 2019.07 (Python3.7.3 64-bit)
python 3.7.3
Cython 0.29.12

環境2

2023/10/01 に再び出くわした時の環境。

- version
windows 10
Visual Studio Express Edition 2017
pyenv-win 3.1.1
python 3.8.10 -> 3.7.3
Cython 3.0.2
swig 4.0.1

-> python 3.8.10 では解決できず、 3.7.3 に下げて4年前と同じ方法で無理やり解決させた。

症状

Cython 実行時エラー

jupyter-notebook
# 参考にした記事: https://qiita.com/pashango2/items/45cb85390193d97523ca
%load_ext Cython

# --- next cell ---
%%cython
def py_fib(n):
    a, b = 0.0, 1.0
    for i in range(n):
        a, b = a + b, a
    return a

# result
...()
-> DistutilsPlatformError: Unable to find vcvarsall.bat

swig 実行時エラー

> python setup.py build_ext --inplace
running build_ext
building '_pafprocess' extension
swigging pafprocess.i to pafprocess_wrap.cpp
C:\swigwin-4.0.1\swig.exe -python -c++ -o pafprocess_wrap.cpp pafprocess.i
error: Unable to find vcvarsall.bat

対処

  1. pythonをコンパイルしたVC++のバージョンを調査
  2. Visual Studioをインストール
    もちろん、1. で調べたバージョンをインストールする
  3. Cythonのソースを無理やり書き換えて、vcvarsall.batを見つけさせた (swig 実行時エラー発生時は不要っぽい?)

他の方法も色々試したんですが...この方法しか成功しませんでした

「なんでこんな方法にしたの?」と思われた方は、ここをご覧くださいな(;_;)

1. pythonをコンパイルしたVC++のバージョンを調査

cmd
C:\Users\PCUser>python
>>> import sys
>>> sys.version
'3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)]'

ということで、コンパイラ VC++ のバージョンは V14.15 (Visual C++ 2017) と判明

Visual Studio のバージョン を sys.version の出力結果からたどる場合、 wikipedia にも情報が書かれているが、

次のサイトの方が詳しい。

2. Visual Studio インストール

2017 ※以下の方法は、今は使えないようです

  1. 次のURLを開く
    https://visualstudio.microsoft.com/ja/vs/express/
  2. 下にスクロールして以下の赤枠位置をクリックしてインストーラーをダウンロード
    image.png
  3. ダウンロードされたファイルを実行
    vs_wdexpress.exe
    特に設定変更などはせず
  4. vcvarsall.batファイルを探す!
    私の場合、ここにあった...↓
    C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Auxiliary\Build

2017 ※代替策 (2023/10/01)

こちらの記事で、 Visual Studio express 2017 のインストール方法が書いてありました。

以下のサイトなどから、VIsual Studio 2022 などのインストーラを入手し、

powershell で、そのファイルがあるフォルダまで移動してから、以下のコマンドを実行します。

powershell
# VisualStudioSetup.exe の部分は、ダウンロードしたファイル名で置き換えてね
.\VisualStudioSetup.exe --channelUri https://aka.ms/vs/15/release/channel --productId Microsoft.VisualStudio.Product.WDExpress

すると、Visual Studio 2017 のインストールが開始できる状態になります。
install し終わったら、念のため windows 本体を再起動しておく。

このインストール方法、一体いつまで使えるのだろうか。。。

とりあえず、ファイルは4年前と同じここにあった。
C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Auxiliary\Build

vcvarsall.png

昔と変わらず。

2019 ※使ってません

ここからダウンロードしたインストーラでインストールできます

※ただし、2019を使った解決策はまだ確立できておらず、この記事にも書いていません。

3. Cythonコードの書き換え

(swig 実行時エラーへの対処場合、やらなくてよさそう?)

Jupyter Notebook上のエラーログには、_msvccompiler.pyというファイルの135行目付近でエラーが発生したと書かれていたので、まずはそのファイルを探す。

ここにあった

  • anaconda で環境構築してた時
    C:\Users\PCUser\Anaconda3\Lib\distutils\_msvccompiler.py
  • pyenv-win で環境構築した時
    C:\Users\PCUser\...\.venv\Lib\site-packages\setuptools\_distutils\_msvccompiler.py

次に、_msvccompiler.pyの処理を追って行くと、次のメソッドでvcvarsallNoneになっているためにエラーが発生していることが判明。

_msvccompiler.py
# 135行目付近
def _get_vc_env(plat_spec):
    if os.getenv("DISTUTILS_USE_SDK"):
        return {
            key.lower(): value
            for key, value in os.environ.items()
        }

    vcvarsall, vcruntime = _find_vcvarsall(plat_spec)
    if not vcvarsall:
        # Jupyter Notebook上ではこのエラーが見える
        raise DistutilsPlatformError("Unable to find vcvarsall.bat")

    # ... 以下略

まずは error 発生直前の_find_vcvarsallメソッドが怪しい。
このメソッドを探すと....

_msvccompiler.py
# 92行目付近
def _find_vcvarsall(plat_spec):
    _, best_dir = _find_vc2017()
    vcruntime = None
    vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'
    if best_dir:
        vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**",
            "Microsoft.VC141.CRT", "vcruntime140.dll")
        try:
            import glob
            vcruntime = glob.glob(vcredist, recursive=True)[-1]
        except (ImportError, OSError, LookupError):
            vcruntime = None

    # ... 以下略

_find_vcvarsallメソッド内に_find_vc2017()なるメソッドを発見。

こいつの戻り値best_dirさえ正しければ、vcvarsall.batファイルも見つけられる気がするのだけれど...

print(best_dir)したらNoneが入ってました。
ぷわー(/・ω・)/

ここで3時間以上経過していたため、完全に面倒くさくなり、best_dirに直接pathを代入させることにしました...

_msvccompiler.py
# 92行目
def _find_vcvarsall(plat_spec):
    # _, best_dir = _find_vc2017()  # もともとあったコード

    # INFO: from this line, cord is added ...
    # tmp_path に正しいpathを投入
    tmp_path = "C:/Program Files (x86)/Microsoft Visual Studio/2017/WDExpress".replace('/', os.sep)
    best_dir = os.path.join(tmp_path, "VC", "Auxiliary", "Build")
    print(best_dir)
    # INFO: until this line, cord is added ...

    vcruntime = None
    vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'
    if best_dir:
        vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**",
            "Microsoft.VC141.CRT", "vcruntime140.dll")
        try:
            import glob
            vcruntime = glob.glob(vcredist, recursive=True)[-1]
        except (ImportError, OSError, LookupError):
            vcruntime = None

    # ... 以下略

この修正を行った後に再度実行したところ、めでたくCythonによるコンパイルが成功しました!!
image.png

補足事項

_msvccompiler.pyを書き換える度に、Jupyter Notebook の kernel を restart する必要があります。
そうしないと、たとえファイルを書き換えても実行結果が変わりませんでした。

参考にした記事

  • WindowsでもCythonを使いたい!

-> Visual Studioが必要と判明

  • 「Unable to find vcvarsall.bat」の対処法

-> PythonをコンパイルしたVC++のバージョンが重要な意味を持つと判明

  • Fix Python 3 on Windows error Microsoft Visual C++ 14.0 is required

-> python3.7にはVisual Studio 2017が必要と判明

  • Installing Cython For Anaconda On Windows (※link切れ)

-> Cythonのソースを直接書き換えるという愚行を試すきっかけ

  • VisualStudio2017 install 方法 (2023/10/01 現在有効)

もし、この記事がなかったら、2023年時点において VisualStudio2017 はインストールできなかった。。

惜しくも参考にできなかった記事

多分こっちのやり方が正統派なんだと思いますです...
CythonExtensionsOnWindows
私の力では、何をすればいいのかわかりませんでした(´・ω・`)

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4