C#からPythonへJSON文字列を送り、少し編集してC#側に戻すサンプル。
Pythonにあまり詳しくないC#経験者向けに書いています。
環境
- Windows10 64bit
- Visual Studio 2022
- .Net6.0
- Newtonsoft.Json
- Python 3.6.8
C#側
標準入出力を介してやり取りする形になります。
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"キーを追加するだけです。
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