概要
pythonで作った処理(主にはtensorflow, pytorch等のディープラーニング系)をGUIから動かして結果を表示したいということがあると思います。
tkinterやpyqtで作っても良いですが、C#のフォームの良さを活かすことで手早くGUIが作ることができます。
また、C#は製造業で使用する検査システム等でよく使われるため、組み込みができると便利です。
tensorflowで作ったモデルを使ってアプリを作るところまでの手順を記事したいと思います。
本記事はまずは準備と動作確認編です。
実際に簡単なフォームアプリを作って、準備と動作確認してみます。
(2023年4月最新の方法です。)
準備ができた方は実践編も参考にしてみてください
前提条件
開発の環境
visualstudio2019 community Version 16.7.7
NuGet パッケージ マネージャー 5.7.0
Anaconda Navigator 1.9.12
C#の環境
.NET Framework 4.7.2
pythonの環境
Python 3.8.5
tensorflow 2.3.0
numpy 1.18.5
C#からpythonnetを呼び出して使ってみる
フォームにラベルを配置してnumpyのバージョン表示、numpyでの簡単な計算をするアプリを作ってみようと思います。
フォームのアプリケーションを作る
注意ポイント:.NETフレームワークのバージョンを4.7以上にしてください
プラットフォーム変更
注意ポイント:構成マネージャーをx64=64bitにしないとうまく動きません
Debugの右の▼ボタンをクリックして構成マネージャーをクリック
アクティブソリューション プラットフォーム(P)の∨をクリック→新規作成をクリック
新しいプラットフォームを入力または選択してください(P)でx64を選択→OKをクリック
Debugの右のAny CPUがx64に変わっていることを確認してください。
pythonnetの導入
以下の操作をしてください。
- ツール
- NuGetパッケージマネージャー
- ソリューションのNuGetパッケージの管理
管理画面が開きましたら以下の「pythonnet」を選択して
インストールしてください。
インストールできたら、ソリューションエクスプローラーに
Python.Runtime
が追加されていることを確認してください。
サンプルコードの作成
このようなフォームを作成してみてください
ソースコード
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Python.Runtime;
namespace pythonnet_numpy_test_2023
{
public partial class Form1 : Form
{
// numpyのモジュールを格納する変数を定義
private dynamic np;
public Form1()
{
InitializeComponent();
// *-------------------------------------------------------------------------
// * python環境をpythonnetに設定
// *-------------------------------------------------------------------------
// DLLの設定
// pythonXX.dllが存在しているパスを定義
var PYTHON_DLL_PATH = (@"自分のpython環境パス\pythonXX.dll");
// PythonDLLに設定
Runtime.PythonDLL = PYTHON_DLL_PATH;
// python標準ライブラリの設定
// python.exeが存在しているフォルダの指定
var PYTHON_HOME = @"自分のpython環境パス";
// 環境変数に定義
Environment.SetEnvironmentVariable("PYTHONHOME", PYTHON_HOME, EnvironmentVariableTarget.Process);
// PythonEngineのPythonHomeに設定
PythonEngine.PythonHome = Environment.GetEnvironmentVariable("PYTHONHOME", EnvironmentVariableTarget.Process);
// 外部ライブラリの設定
// 外部ライブラリが存在しているフォルダの設定
var MODULE_PATH = @"仮想環境のパス";
// PythonPathに外部ライブラリを追加
PythonEngine.PythonPath = string.Join(
Path.PathSeparator.ToString(),
new string[] {
PythonEngine.PythonPath,
Path.Combine(MODULE_PATH, @"Lib\site-packages"),
}
);
// PythonEngineの初期化
PythonEngine.Initialize();
// pythonの処理をする=numpyの定義とバージョンをラベルに表示させる
using (Py.GIL())
{
// numpyのインポート
np = Py.Import("numpy");
// numpyのバージョンを変数に格納
dynamic np_version = np.__version__;
// string型にして文字列と連結させラベルに表示
labelNumpyVersion.Text = "numpyバージョン:" + np_version.ToString();
}
}
/// <summary>
/// numpyのライブラリを使った簡単な計算
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCalc_Click(object sender, EventArgs e)
{
// 簡単な計算をして変数に格納
dynamic result = np.cos(np.pi / 3);
// ToStringしなくても文字列にくっつけると勝手に型を変えてくれる
labelResult.Text = "np.cos(np.pi / 3)=" + result;
}
}
}
基本的には通常のC#のフォームアプリを作成方法と変わりませんが、ポイントがいくつかあります。
1.フォームをロードするときにpythonnetの初期化をする
フォームをロードするときのメソッドに初期化のコードを追記しましょう。
追記する部分が3つあります。
(1)PythonのDLLのパスを設定
anacondaの場合は仮想環境ごとにpython自体もインストールしますので
Anaconda3\envs\環境名
を設定します。
venv等を使っている場合には公式のpythonインストーラーで入れるので
AppData\Local\Programs\Python\バージョンの毎のpython
の中にpythonXX.dllやpython.exeがあると思いますのでそのパスを設定します。
※XXにはpythonのバージョンが入ります ex)python3.8→38
var PYTHON_DLL_PATH = (@"自分のpython環境パス\pythonXX.dll");
(2)Python.exeが存在するパスを設定
先ほど同様に
anacondaの場合は仮想環境ごとにpython自体もインストールしますので
Anaconda3\envs\環境名
を設定します。
venv等を使っている場合には公式のpythonインストーラーで入れるので
AppData\Local\Programs\Python\バージョンの毎のpython
の中にpythonXX.dllやpython.exeがあると思いますのでそのパスを設定します。
var PYTHON_HOME = @"自分のpython環境パス";
(3)外部ライブラリが存在するパスを設定
anacondaで仮想環境を作った場合は
Anaconda3\envs\環境名
venvで仮想環境を作った場合は
自分でパスを設定しますので
そのパスを設定してください。
var MODULE_PATH = @"仮想環境のパス";
2.実際にpythonのコードをC#で実装
1つポイントとしてフォームアプリの場合は色々なコントロールでnumpyを使いたいのでインポートしたときに格納するメンバー変数を定義しておく必要があります。
まとめると以下の通りになります。
メンバー変数の定義
public partial class Form1 : Form
{
/// <summary>
/// pythonライブラリを共有して使うための変数
/// </summary>
public dynamic np;
numpyの定義とバージョン情報の表示
// pythonの処理をする=numpyの定義とバージョンをラベルに表示させる
using (Py.GIL())
{
// numpyのインポート
np = Py.Import("numpy");
// numpyのバージョンを変数に格納
dynamic np_version = np.__version__;
// string型にして文字列と連結させラベルに表示
labelNumpyVersion.Text = "numpyバージョン:" + np_version.ToString();
}
numpyの使用
// 簡単な計算をして変数に格納
dynamic result = np.cos(np.pi / 3);
最後に
C#でpythonの処理をそのまま使えるとアプリの幅が広がると思いますので是非試してみてください。
また、準備ができた方は実践編も読んでみてください。
コメント
[…] C#にpythonで作った処理を組み込む【pythonnet準備+確認編 2021年2月最新】 […]