【簡単】C#.NETからPythonを呼び出すサンプル

C#.NETからPythonのスクリプトファイルを実行するサンプルです。使用しているのはpythonnetです。他にクラスProcessでコントロールする方法もありますが、pythonnetの方が記述がすっきりしているので、こっちを使ってます。

ユーザーが作成したpythonのスクリプトを実行させて、そのレスポンスを取得できます。下のようにPython.Runtime.dllを間に挟んで相互のやり取りをしています。

exe → Python.Runtime.dll → Python.dll

Pythonnetの導入とVisualStudioの設定

設定は、たった二か所だけです。

Pythonnetのインストール

  1. VisualStudioのメニュー → ツール → NuGetパッケージマネージャ → ソリューションのNuGetパッケージ管理で管理画面を開きます。
  2. 参照を選択
  3. pythonnet_netstarndardで検索
  4. インストール

非推奨のものを避け、pythonnet_netstandard_py38_winを入れました。

VisualStudioのソリューションの設定

デフォルトは、”Any CPU”になっていますが、Pythonに合わせ64bitにします。構成マネージャで、アクティブソリューションプラットフォームをx64に設定すると、64bitになります。

C#.NETからpyファイルを呼び出すサンプル

サンプルのため非常にシンプルなソースですが、設定の自由度は高くなっています。

Pythonのスクリプトファイル 呼び出される側

hogehoge.pyのfoo()が呼ばれます。

# hogehoge.py
def foo(val):
    val += 5
    return f"result {val}"

if __name__ == '__main__':
    foo(12)

C# 呼び出し元

using System;
using System.Windows.Forms;
using Python.Runtime;
using System.IO;

namespace CallPython
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //  モジュールのあるパスを追加
            //  exeのあるフォルダは、追加不要
            string[] pathes = {
                PythonEngine.PythonPath,
                Path.Combine(@"~")   //< Python Script ファイルのあるフォルダを設定
            };
            PythonEngine.PythonPath = string.Join(Path.PathSeparator.ToString(), pathes);
            Console.WriteLine(PythonEngine.PythonPath);

            PythonEngine.Initialize();

            //  Pythonのオブジェクト取得・操作前にロックが必要
            IntPtr pythonLock = PythonEngine.AcquireLock();
 
            //  モジュールの実行と戻り値の取得
            PyDict pyDict = new PyDict();
            PythonEngine.Exec("import hogehoge", locals: pyDict.Handle);
            var ret = PythonEngine.Eval("hogehoge.foo(58)", locals: pyDict.Handle);
            Console.WriteLine(ret);

            PythonEngine.ReleaseLock(pythonLock);

            PythonEngine.Shutdown();
        }
    }
}

PythonEngine.PythonPathは、実行したいpythonモジュールのあるフォルダを設定します。.NETの実行バイナリのフォルダはデフォルトでパスが通っているため、exeと同じフォルダににPythonのモジュールを配置すればPythonPathを設定する必要はありません。

実行結果

'CallPython.exe' (CLR v4.0.30319: CallPython.exe): '__CodeGenerator_Assembly' が読み込まれました。
result 63

戻り値の受け取り

python側から文字列を得られるので、JSONも使えます。

コメント

タイトルとURLをコピーしました