22
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C# から Python を呼ぶ Pythonnet の使い方

Last updated at Posted at 2022-11-20

はじめに

機械学習や最適化、数値計算はPythonのライブラリがC#に対して非常に充実しているので、C#で簡単にできないことが多いしラッパーやC#むけに書き換えるのも時間がかかる。
そういった場合に役に立つライブラリ Pythonnet について紹介します。

このライブラリは、C#からPythonの関数を呼び出すことが出来る非常に便利なライブラリで.NET Foundationからもサポートを受けて開発されています。
PythonからC#を呼び出す機能も提供されていてそちらの方が記事が多いですが、C#からPythonを呼び出す記事はあまりなかったので備忘録的に作成しました。

型について

C#の型のままではPythonの関数に値を渡せないので、Python用の方に変換する必要があります。
基本的にはPyHoge型が存在してそれに変換します。

文字列

string str = "Foo";
var pyStr = new PyString(str);

整数型

int intNum = 1;
var pyInt = new PyInt(intNum);

倍精度浮動小数点型

double doubleNum = 4.5;
var pyFloat = new PyFloat(doubleNum);

リスト

// C# のリストではなく Python(動的型付け) のリストなので
// List<T> のTような型指定はない
var strList = new PyList();

// Python のリストなので Add ではなく Append
list.Append(new PyString("foo"));
list.Append(new PyString("bar"));
list.Append(new PyString("baz"));

// 以下のようにも作れる
var pyObj = new PyObject[] {new PyInt(3), new PyInt(2), new PyInt(1) };
var pyList = new PyList(pyObj);

連想配列

var dict = new PyDict();
dict.SetItem("key1", new PyFloat(10.0));
dict.SetItem("key2", new PyFloat(20.0));

拡張メソッド

これまでPyHoge型をnewを使って作成する方法について書いてきたが、よく使う型については拡張メソッドが用意されているので、基本的にはC#そのままで書いていても問題なく変換できる。

//リストの例
var csList = new List<double>{1, 2, 3, 4};

// ToPython()メソッドがPythonに変換してくれる
PyObject py_list = csList.ToPython();

ライブラリのインポート

単純なインポートなら以下のように書ける。

import numpy

dynamic numpy = Py.Import("numpy")

from A import B の場合は以下のようにすればimportはできる。

from math import radians

dynamic radians = Py.Import("math").GetAttr("radians");

もちろん以下のようにも書ける

PyModule ps = Py.CreateScope();
ps.Exec(
    "from math import radians"
);
dynamic radians = ps.Get("radians");

公式のサンプル

C# で Numpy を使う例

既存のライブラリは簡単にC#側から呼ぶことが出来る。公式に記載されているC#からNumpyを呼び出す例は以下。

IDEのコードヒントは全くでないのでPython側のライブラリをよく把握していないとC#単体でPythonのコードをタイポなく呼ぶのは難しい。
だいたいの場合は一回Pythonで書いてからC#に書き換える方が楽な場合が多い

static void Main(string[] args)
{
    PythonEngine.Initialize();
    using (Py.GIL())
    {
        dynamic np = Py.Import("numpy");
        Console.WriteLine(np.cos(np.pi * 2));

        dynamic sin = np.sin;
        Console.WriteLine(sin(5));

        double c = (double)(np.cos(5) + sin(5));
        Console.WriteLine(c);

        dynamic a = np.array(new List<float> { 1, 2, 3 });
        Console.WriteLine(a.dtype);

        dynamic b = np.array(new List<float> { 6, 5, 4 }, dtype: np.int32);
        Console.WriteLine(b.dtype);

        Console.WriteLine(a * b);
        Console.ReadKey();
    }
}

// Output
// 1.0
// -0.958924274663
// -0.6752620892
// float64
// int32
// [  6.  10.  12.]

Pythonの関数をC#側で書いてC#側で呼ぶ方法

既存のライブラリを呼ぶまでもないものや、C#で書くと面倒なものは以下のように文字列としてC#上で書くとPythonコードとして使うことが出来る

PythonEngine.Initialize();
using (Py.GIL())
{
    PyModule ps = Py.CreateScope();
    ps.Exec(
        "def add(a, b):\n" +
        "  return a + b\n" // Python を書いているのでインデントを忘れずに
    );

    // ここで上記で作成した add メソッドをC#側に取得している
    dynamic add = ps.Get("add");
    var result = add(1, 2)  // result = 3
}

22
19
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
22
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?