以前にC#からPythonのディープラーニングフレームワークを呼び出すいくつかの方法を記事にした。
- gRPCでC#とPythonを連携する - TadaoYamaokaの開発日記
- SocketでC#とPythonを連携する - TadaoYamaokaの開発日記
- TensorFlowのC#バインディング - TadaoYamaokaの開発日記
- ML.NETからTensorFlowを使う - TadaoYamaokaの開発日記
- C#からLibTorchを使ってMNISTデータセットを学習する - TadaoYamaokaの開発日記
最後のlibTorchは、Pythonではないが、速度を出したい場合には選択肢になる。
しかし、モデルの定義をC++で実装する必要があり、メンテナンス性を考慮するとPythonからPyTorchを利用したい。
上記の他の方法は、機能が不足していたり、プロセス間通信のオーバーヘッドが大きすぎて速度がでなかったりで難がある。
最近、ハースストーンのAIの論文を読んでいたら、PythonNet(Python for .NET)で、C#からPythonを呼び出せることを知った。
てっきりPythonから.Netを利用するためだけのライブラリかと思ってスルーしていた。
公式ページの説明の下の方の「Embedding Python」を読めば、.NetからPythonを利用する方法について書かれていた。
メリット
PythonNetは、.NetによるPython実装ではなく、インストールされているPythonそのものが.Netのプロセスで実行される。
そのため、インストールされているPythonで動くものはすべて動くので互換性や機能不足で問題が起きない。
また、プロセス間通信がないため、速度面のボトルネックが少ない。
データのマーシャリングを自動で行ってくれるため、C#の変数をそのままPythonに渡せて、Pythonから結果をC#のオブジェクトとして受け取ることができる。
ということで、とても扱いやすいライブラリであることが分かった。
いろいろ試してみて、WindowsでもLinuxでも.Net Core 2.1から利用することができたので、インストール方法と使い方を記しておく。
インストール方法は、公式のWikiに記載があるが記述が少なくわかりにくかった。
Python環境構築
Python環境はすでに利用しているものが利用できる。
対応しているPythonのバージョンは、3.7なので3.8の場合は新たにPython環境の構築が必要になる。
Anacondaの場合は、アーカイブからAnaconda3-2019.10をインストールする。
PythonNetインストール
Windowsの場合
Windowsの場合、ビルド済みパッケージが利用できる。
dotnet add package Python.Runtime.NETStandard
を実行するだけでよい。
環境変数PATHにPythonをインストールしたディレクトリ(python37.dllのあるディレクトリ)を追加する。
Anaconda3のインストール時にPATHを設定している場合は不要。
Linuxの場合
※2020/11/1 追記 Linux向けには「pythonnet_netstandard_py37_linux」パッケージが使用できるため、下記記載のビルドは不要だった。
各プロットフォームと各Pythonのバージョンに対応したパッケージは、NuGet Galleryで検索できる。
Linuxの場合、ビルドが必要になる。
GitHubからリポジトリをクローンする。
git clone https://github.com/pythonnet/pythonnet
clangが必要なため、インストールされてない場合はインストールする。
sudo apt install clang
setup.pyでwheelを作成するとビルドされる。
python setup.py bdist_wheel --xplat
※「--xplat」オプションは.Net Coreから利用する場合に必要
Pythonから.Netを利用する場合は、ビルドされたwheelをインストールするが、.NetからPythonを利用する場合は必要ない。
build/lib.linux-x86_64-3.7/netcoreapp2.0
にビルドされたPython.Runtime.dllを使用する。
Python.Runtime.dllをC#プロジェクトのディレクトリにコピーして、.csprojに以下を追記する。
<ItemGroup> <Reference Include="Python.Runtime"><HintPath>Python.Runtime.dll</HintPath></Reference> </ItemGroup>
環境変数LD_LIBRARY_PATHを設定する。
export LD_LIBRARY_PATH=/home/xxx/anaconda3/lib:$LD_LIBRARY_PATH
※Pythonのインストール場所に合わせる。
サンプルコード
以下は、Python環境にインストールされたPyTorchをインポートしてバージョンを表示するC#コードの例である。
WindowsでもLinuxでも同じ。
using System; using System.IO; using Python.Runtime; namespace pythonnettest { class Program { static void Main(string[] args) { var PYTHON_HOME = Environment.ExpandEnvironmentVariables(@"C:\Anaconda3"); PythonEngine.PythonHome = PYTHON_HOME; using (Py.GIL()) { dynamic torch = Py.Import("torch"); dynamic version = torch.__version__; Console.WriteLine(version); } } } }
※PYTHON_HOMEは、Pythonをインストールしたディレクトリに合わせる。
実行結果:
1.3.1