Windows の pip で Pygrib をインストールする
気象庁が出している数値予報データなどの GPV (Grid Point Value) を扱う Python ライブラリに Pygrib というものがあります。この記事では Windows 10 で pip を使って Pygrib を入れようとしたらビルドエラーが出てうまくいかなかったため、頑張って何とかした話です。
概要と環境
Pygrib を pip でインストールする手順を簡単にまとめると次のとおりです。
- grib_api を Visual Studio 経由でビルドする
- ビルドしたライブラリなどのパスを設定して pip でインストールする
全体的にはブログ記事「pygrib が Microsoft Visual Studio でビルド出来るようになる話」を参考にしました。
実行環境は以下の通りでした。
- Windows 10 (バージョン 21H2)
- Python 3.9.13
ただ、pip だとうまくビルドできなかったのですが、Anaconda 環境では普通に conda install できました<ref>conda install -c conda-forge pygrib</ref>。したがって以下の記述は「pygrib を利用したいけど、Windows でしかも Anaconda は使いたくない」という人向けのメモになります。
pip で入らない
まずは pip を使ってインストールを試みましたが、ビルドエラーで怒られました。
PS C:\Users\sample> python.exe -m pip install pygrib
Collecting pygrib
Using cached pygrib-2.1.4.tar.gz (21.8 MB)
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... done
Requirement already satisfied: pyproj in c:\users\sample\appdata\local\programs\python\python39\lib\site-packages (from pygrib) (3.4.0)
Requirement already satisfied: numpy in c:\users\sample\appdata\local\programs\python\python39\lib\site-packages (from pygrib) (1.22.4)
Requirement already satisfied: certifi in c:\users\sample\appdata\local\programs\python\python39\lib\site-packages (from pyproj->pygrib) (2022.5.18.1)
Building wheels for collected packages: pygrib
Building wheel for pygrib (pyproject.toml) ... error
error: subprocess-exited-with-error
× Building wheel for pygrib (pyproject.toml) did not run successfully.
│ exit code: 1
╰─> [14 lines of output]
eccodes not found, build may fail...
running bdist_wheel
running build
running build_py
creating build
creating build\lib.win-amd64-cpython-39
creating build\lib.win-amd64-cpython-39\pygrib
copying src\pygrib\__init__.py -> build\lib.win-amd64-cpython-39\pygrib
running build_ext
cythoning src/pygrib/_pygrib.pyx to src/pygrib\_pygrib.c
C:\Users\sample\AppData\Local\Temp\pip-build-env-gaold049\overlay\Lib\site-packages\Cython\Compiler\Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: C:\Users\sample\AppData\Local\Temp\pip-install-qsivpw8o\pygrib_3b7fe8055b8a46b298e0ead62563ca4a\src\pygrib\_pygrib.pyx
tree = Parsing.p_module(s, pxd, full_module_name)
building 'pygrib._pygrib' extension
error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for pygrib
Failed to build pygrib
ERROR: Could not build wheels for pygrib, which is required to install pyproject.toml-based projects
エラー文 “error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/" より Microsoft Visual C++ のバージョン 14.0 以降のものがないということがわかったので、指示に従って Microsoft C++ Build Tools からインストーラをダウンロードし、Visual C++ をインストールします。
Visual C++ をインストールしたあとで、再び pip install をすると違うエラーで怒られました。
PS C:\Users\sample> python.exe -m pip install pygrib
Collecting pygrib
Using cached pygrib-2.1.4.tar.gz (21.8 MB)
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... done
Requirement already satisfied: pyproj in c:\users\sample\appdata\local\programs\python\python39\lib\site-packages (from pygrib) (3.4.0)
Requirement already satisfied: numpy in c:\users\sample\appdata\local\programs\python\python39\lib\site-packages (from pygrib) (1.22.4)
Requirement already satisfied: certifi in c:\users\sample\appdata\local\programs\python\python39\lib\site-packages (from pyproj->pygrib) (2022.5.18.1)
Building wheels for collected packages: pygrib
Building wheel for pygrib (pyproject.toml) ... error
error: subprocess-exited-with-error
× Building wheel for pygrib (pyproject.toml) did not run successfully.
│ exit code: 1
╰─> [22 lines of output]
eccodes not found, build may fail...
running bdist_wheel
running build
running build_py
creating build
creating build\lib.win-amd64-cpython-39
creating build\lib.win-amd64-cpython-39\pygrib
copying src\pygrib\__init__.py -> build\lib.win-amd64-cpython-39\pygrib
running build_ext
cythoning src/pygrib/_pygrib.pyx to src/pygrib\_pygrib.c
C:\Users\sample\AppData\Local\Temp\pip-build-env-a12alw0y\overlay\Lib\site-packages\Cython\Compiler\Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: C:\Users\sample\AppData\Local\Temp\pip-install-71nznokm\pygrib_743dda9af7fb4c6ba78e7cb596d5d4cf\src\pygrib\_pygrib.pyx
tree = Parsing.p_module(s, pxd, full_module_name)
building 'pygrib._pygrib' extension
creating build\temp.win-amd64-cpython-39
creating build\temp.win-amd64-cpython-39\Release
creating build\temp.win-amd64-cpython-39\Release\src
creating build\temp.win-amd64-cpython-39\Release\src\pygrib
"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.33.31629\bin\HostX86\x64\cl.exe" /c /nologo /O2 /W3 /GL /DNDEBUG /MD -IC:\Users\sample\AppData\Local\Programs\Python\Python39\include -IC:\Users\sample\AppData\Local\Programs\Python\Python39\Include -IC:\Users\sample\AppData\Local\Temp\pip-build-env-a12alw0y\overlay\Lib\site-packages\numpy\core\include "-IC:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.33.31629\include" "-IC:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\VS\include" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\um" "-IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\shared" "-IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\winrt" "-IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\cppwinrt" /Tcsrc/pygrib\_pygrib.c /Fobuild\temp.win-amd64-cpython-39\Release\src/pygrib\_pygrib.obj
_pygrib.c
C:\Users\sample\AppData\Local\Temp\pip-build-env-a12alw0y\overlay\Lib\site-packages\numpy\core\include\numpy\npy_1_7_deprecated_api.h(14) : Warning Msg: Using deprecated NumPy API, disable it with #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
src/pygrib\_pygrib.c(756): fatal error C1083: include ファイルを開けません。'grib_api.h':No such file or directory
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Tools\\MSVC\\14.33.31629\\bin\\HostX86\\x64\\cl.exe' failed with exit code 2
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for pygrib
Failed to build pygrib
ERROR: Could not build wheels for pygrib, which is required to install pyproject.toml-based projects
エラー文 “fatal error C1083: include ファイルを開けません。’grib_api.h’:No such file or directory" より “grib_api.h" がないのが原因だとわかりました。
grib_api のために ecCodes をビルドする
grib_api.h は ecCodes に含まれているので、まず ecCodes のソースを公式サイトからダウンロードします。ここでは記事執筆時点での最新版である version 2.27.0 のソースコードをダウンロードしました。
ソースコードは tar.gz で固められているので、解凍します。私は WSL の Linux 経由で解凍してしまいました。Windows ネイティブの機能だけで解凍しようとすると、場合によってはちょっと大変かもしれません。解凍すれば eccodes-2.27.0-Source というフォルダが出てきます。
できたフォルダの中、eccodes-2.27.0-Source/windows/msvc/grip_api.sln を開きます。これは Visual Studio 用のプロジェクトファイルなので、適切に関連付けされていれば Visual Studio が起動するはずです。
ソリューションの再ターゲット (Toolset 変換)
eccodes のソースに同梱されている Visual Studio 用のプロジェクトファイルは古いバージョンの Visual Studio によってできているらしいので、最新版に合わせたプロジェクトに更新(再ターゲット、Toolset の変換)します。私の場合は、最初の起動時に以下のようなダイアログがでて再ターゲットを促されました。OK を選択して再ターゲット (Toolset の変換) を行います。
もしこの画面が出なかった場合は右端のソリューションエクスプローラーにあるソリューション名を右クリックして出てくるメニューから「ソリューションの再ターゲット」を選択して更新します。
eccodes_version.h を作成する
手動で eccodes-2.27.0-Source/src/eccodes_versions.h を作成します。まず同じフォルダにある eccodes-2.27.0-Source/src/eccodes_versions.h.in をコピーして、eccodes_versions.h を作成し、中の情報を書き換えます。
基本的に @ で囲まれているところを書き換えます。下記に示す例は、元々の eccodes_versions.h.in の内容をコメントアウトしつつ、変更すべき内容を並べて書いています。
/*
* (C) Copyright 2005- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
*
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
*/
#ifndef eccodes_version_H
#define eccodes_version_H
// #define ECCODES_VERSION_STR "@eccodes_VERSION_STR@" // 書き換え前
#define ECCODES_VERSION_STR "2.27.0" // 書き換え後
// #define ECCODES_MAJOR_VERSION @eccodes_VERSION_MAJOR@ // 書き換え前
#define ECCODES_MAJOR_VERSION 2 // 書き換え後
// #define ECCODES_MINOR_VERSION @eccodes_VERSION_MINOR@ // 書き換え前
#define ECCODES_MINOR_VERSION 27 // 書き換え後
// #define ECCODES_REVISION_VERSION @eccodes_VERSION_PATCH@ // 書き換え前
#define ECCODES_REVISION_VERSION 0 // 書き換え後
#define ECCODES_VERSION (ECCODES_MAJOR_VERSION*10000+ECCODES_MINOR_VERSION*100+ECCODES_REVISION_VERSION)
#endif /* eccodes_version_H */
バージョン情報を書き換える感じです。この例の場合、書き換えるのは以下のような感じです。
- @eccodes_VERSION_STR@ → 2.27.0 (ダブルクォーテーションで囲まれているのに注意!)
- @eccodes_VERSION_MAJOR@ → 2
- @eccodes_VERSION_MINOR@ → 27
- @eccodes_VERSION_PATCH@ → 0
設定すべき数値はソースコードのバージョンによって異なります。最初の eccodes_VERSION_STR は文字列なので、ダブルクォーテーションで囲み、そのあとドット区切りで示されているバージョンの数値をそれぞれ設定します。
ビルドする
grib_api をビルドします。ビルドは Visual Studio 画面中のコマンドプロンプト (PowerShell) で以下のコマンドを実行しました。
MSBuild.exe -p:Configuration=Release -p:platform=x64 grib_api.sln
私の環境では 2 分程度かかりました。Warning (警告) はたくさん出ますが、エラーはなく終了します。
環境変数を設定して Pygrib をインストール
grib_api をビルドしたことで Pygrib をインストールするのに必要なライブラリができたので、インストールします。ちなみに grib_api をビルドしたのと同じ Visual Studio 内のコマンドプロンプトで pip install しようとしたら、私の環境ではうまくいかなくてハマった(原因の想像は後述)ので、新しく PowerShell を起動した方がいいかもしれません。
環境変数を設定する
pip コマンドでインストールを始める前に環境変数を設定します。LIB と INCLUDE を変更します。
$oldlib = [System.Environment]::GetEnvironmentVariable("LIB")
$oldlib = "C:\Path\to\src\eccodes-2.27.0-Source\windows\msvc\grib_api_lib\x64\Release;" + $oldlib
[System.Environment]::SetEnvironmentVariable("LIB", $oldlib)
$oldinc = [System.Environment]::GetEnvironmentVariable("INCLUDE")
$oldinc = "C:\Path\to\src\eccodes-2.27.0-Source\src;" + $oldinc
[System.Environment]::SetEnvironmentVariable("INCLUDE", $oldinc)
それぞれ元々設定されている環境変数を消さないようにするため、わざわざ変数に入れてから設定しています。
pip install を試みる(失敗)
環境変数を設定後、pip でインストールを試みます。
Python.exe -m pip install pygrib
しかし失敗します(エラー例は失敗する環境をもう一度再現できたら掲載します)。ライブラリのビルド環境(64 bit)と Python の実行環境(32 bit)が合わないというエラーが出ました。これはシステムで持っている Python 環境とは別に Visual Studio で持っている Python 環境があって、起動している Python が異なるのかもしれません。
pip install を試みる(成功)
改めて PowerShell を起動し、pip install するとうまくいきます。
Python.exe -m pip install pygrib
めでたしめでたし……ではありませんでした。もう少し続きます。
Pygrib 実行時に必要な環境変数の設定
めでたくインストールできたので早速 import して実行を試みると次のように怒られます。
ECCODES ERROR : Unable to find definition files directory
ECCODES ERROR : Unable to find boot.def. Context path=(null)
Possible causes:
- The software is not correctly installed
- The environment variable ECCODES_DEFINITION_PATH is defined but incorrect
ecCodes assertion failed: `0' in C:\Path\to\eccodes-2.27.0-Source\src\grib_context.c:226
ECCODES_DEFINITION_PATH が指定されていないとエラーを吐いています。そのため、最初に ecCodes をビルドしたときに使用したフォルダの definitions フォルダを環境変数に設定してやります。
[System.Environment]::SetEnvironmentVariable("ECCODES_DEFINITION_PATH", "C:\path\to\eccodes-2.27.0-Source\definitions")
これで無事動かせるようになりました。本当のめでたしめでたし。
しかし毎回立ち上げるたびに設定せねばならないので、システムの環境変数として設定しておいたほうがいいかもしれません。
ディスカッション
コメント一覧
まだ、コメントがありません