1
1

More than 1 year has passed since last update.

C# から Python へ JSON の受け渡し

Last updated at Posted at 2021-11-19

C#からPythonへJSON文字列を送り、少し編集してC#側に戻すサンプル。
Pythonにあまり詳しくないC#経験者向けに書いています。

環境

  • Windows10 64bit
  • Visual Studio 2022
  • .Net6.0
  • Newtonsoft.Json
  • Python 3.6.8

C#側

標準入出力を介してやり取りする形になります。

Program.cs
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Diagnostics;

// Pythonファイルのパス
string pythonFile = "Program.py";

// Python側に渡すJSON
JObject inputJObj = JObject.Parse(@"{
  'CPU': 'Intel',
  'Drives': [
    'DVD read/writer',
    '500 gigabyte hard drive'
  ]
}
");

var process = new Process
{
    StartInfo = new ProcessStartInfo("python.exe")
    {
        UseShellExecute = false,
        RedirectStandardOutput = true,
        Arguments =
            pythonFile +
            " " +
            JsonConvert.SerializeObject(inputJObj)
                .Replace("\"", "\\\"\"") // 「"」を「\""」にエスケープする
    }
};

process.Start();
StreamReader streamReader = process.StandardOutput;
string? pythonStdOut = streamReader.ReadLine();
process.WaitForExit();
process.Close();

if (pythonStdOut != null)
{
    JObject outputJObj = JObject.Parse(pythonStdOut);
    Console.WriteLine(outputJObj);
}
else
{
    Console.WriteLine("pythonから値が返ってきませんでした");
}

JSONを引数で渡す場合は「"」を「\""」にエスケープしないと
Python側に「"」が一切ないjson文字列が送られてしまいjson.decoder.JSONDecodeErrorになってしまいます。

Python側

していることは"Memory"キーを追加するだけです。

Program.py
import sys
import json

arg = sys.argv[1]
inputObj = json.loads(arg)
inputObj["Memory"] = "16 GB" # "Memory"キーを追加するだけ
print(json.dumps(inputObj, ensure_ascii=False))

sys.argv[1]でjson文字列を受け取ります。
sys.argv[0]には自ファイル名が入っています。

実行

DebugフォルダにPythonファイルが存在しないため、エラーになります。

python.exe: can't open file 'Program.py': [Errno 2] No such file or directory

プロジェクトのプロパティから、ビルド後のイベントとして
Pythonファイルのコピーを登録します。

copy Program.py bin\Debug\net6.0\Program.py

これでちゃんと動きます。

{
  "CPU": "Intel",
  "Drives": [
    "DVD read/writer",
    "500 gigabyte hard drive"
  ],
  "Memory": "16 GB"
}

補足

  • C#側でSystem.ComponentModel.Win32Exceptionが出た
System.ComponentModel.Win32Exception
  HResult=0x80004005
  Message=An error occurred trying to start process 'python.exe' with working directory 'D:\C#\CSharp-Python\CSharp-Python\bin\Debug\net6.0'. 指定されたファイルが見つかりません。
  Source=System.Diagnostics.Process
  スタック トレース:
   場所 System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
   場所 System.Diagnostics.Process.Start()
   場所 Program.<Main>$(String[] args) (D:\C#\CSharp-Python\CSharp-Python\Program.cs):行 126

Pythonがインストールされていないか、Pathが通っていないと思われます。

Pythonインストーラの最後に「PATHに追加する」のチェックがあるので要チェックです。初期値が未チェックなので分かりにくいです。

バージョン表示がされればOKです。

python -V
# "Python 3.x.x" が表示されればOK
  • Python側でModuleNotFoundErrorが出た
Traceback (most recent call last):
  File "Program.py", line 4, in <module>
    import psycopg2
ModuleNotFoundError: No module named 'psycopg2'

この例だと「psycopg2モジュールが見つかりません」ということなのでインストールすればOKです。

python -m pip install psycopg2

こういうのもありました。
https://github.com/pythonnet/pythonnet

1
1
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
1
1