この種の質問は、これまでさまざまな程度で質問されてきましたが、簡潔な方法で回答されていないと感じているため、もう一度質問します。
Pythonでスクリプトを実行したい。これだとしましょう:
if __== '__main__':
with open(sys.argv[1], 'r') as f:
s = f.read()
print s
ファイルの場所を取得して読み取り、その内容を印刷します。それほど複雑ではありません。
さて、C#でこれを実行するにはどうすればよいですか?
これは私が今持っているものです:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;
start.Arguments = args;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
code.py
の場所をcmd
として、filename
の場所をargs
として渡すと、機能しません。 python.exe
をcmd
として渡し、次にcode.py filename
をargs
として渡すように言われました。
しばらく探していましたが、IronPythonなどの使用を提案している人しか見つけることができません。ただし、C#からPythonスクリプトを呼び出す方法が必要です。
いくつかの明確化:
C#から実行する必要があり、出力をキャプチャする必要があり、IronPythonなどは使用できません。どんなハックでも大丈夫です。
追伸:私が実行している実際のPythonコードはこれよりもはるかに複雑であり、C#で必要な出力を返します。C#コードは絶えずPythonを呼び出します。
これは私のコードです:
private void get_vals()
{
for (int i = 0; i < 100; i++)
{
run_cmd("code.py", i);
}
}
動作しない理由は、UseShellExecute = false
があるためです。
シェルを使用しない場合は、python実行可能ファイルへの完全なパスをFileName
として指定し、Arguments
文字列を作成して、スクリプトと読み取りたいファイルの両方を指定する必要があります。
また、UseShellExecute = false
でない限りRedirectStandardOutput
を使用できないことに注意してください。
引数文字列がどのようにPython用にフォーマットされるべきかはよくわかりませんが、次のようなものが必要です:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "my/full/path/to/python.exe";
start.Arguments = string.Format("{0} {1}", cmd, args);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
IronPythonを使用する場合は、C#でスクリプトを直接実行できます。
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
private static void doPython()
{
ScriptEngine engine = Python.CreateEngine();
engine.ExecuteFile(@"test.py");
}
C#プロジェクトを作成し、次のコードを記述します。
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
run_cmd();
}
private void run_cmd()
{
string fileName = @"C:\sample_script.py";
Process p = new Process();
p.StartInfo = new ProcessStartInfo(@"C:\Python27\python.exe", fileName)
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Console.ReadLine();
}
}
}
「Python C#テスト」を印刷
C#のコンソールに 'Python C#Test'が表示されます。
私は同じ問題にぶつかりましたが、Master Moralityの答えは私にはそれをしませんでした。前の回答に基づいた以下が機能しました:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;//cmd is full path to python.exe
start.Arguments = args;//args is path to .py file and any cmd line args
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
例として、cmd行引数100でtest.pyを実行する場合、cmdは@C:/Python26/python.exe
になり、argsはC://Python26//test.py 100
になります。pyファイルのパスには@記号がないことに注意してください。
これに注意を引くためにも:
https://code.msdn.Microsoft.com/windowsdesktop/C-and-Python-interprocess-171378ee
それは素晴らしく機能します。
実際、Csharp(VS)とPythonをIronPythonで簡単に統合できます。それほど複雑ではありません...クリス・ダナウェイがすでに回答セクションで述べたように、私は自分のプロジェクトのためにこの統合を構築し始めました。 Nはとてもシンプルです。次の手順を実行するだけで、結果が得られます。
ステップ1:VSを開き、新しい空のConsoleAppプロジェクトを作成します。
ステップ2:ツールに移動-> NuGetパッケージマネージャー->パッケージマネージャーコンソール。
ステップ3:この後、ブラウザでこのリンクを開き、NuGetコマンドをコピーします。リンク: https://www.nuget.org/packages/IronPython/2.7.9
ステップ4:上記のリンクを開いた後、PM> Install-Package IronPython -Version 2.7.9コマンドをコピーして、VSのNuGetコンソールに貼り付けます。サポートパッケージをインストールします。
ステップ5:これは、Python.exeディレクトリに保存されている.pyファイルを実行するために使用したコードです。
using IronPython.Hosting;//for DLHE
using Microsoft.Scripting.Hosting;//provides scripting abilities comparable to batch files
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
class Hi
{
private static void Main(string []args)
{
Process process = new Process(); //to make a process call
ScriptEngine engine = Python.CreateEngine(); //For Engine to initiate the script
engine.ExecuteFile(@"C:\Users\daulmalik\AppData\Local\Programs\Python\Python37\p1.py");//Path of my .py file that I would like to see running in console after running my .cs file from VS.//process.StandardInput.Flush();
process.StandardInput.Close();//to close
process.WaitForExit();//to hold the process i.e. cmd screen as output
}
}
ステップ6:コードを保存して実行する
stdin/stout
に問題があります-ペイロードサイズが数キロバイトを超えるとハングします。 Python関数は、いくつかの短い引数だけでなく、大きくなる可能性のあるカスタムペイロードで呼び出す必要があります。
少し前に、Redisを介して異なるマシンにタスクを分散できる仮想アクターライブラリを作成しました。 Pythonコードを呼び出すために、Pythonからのメッセージをリッスンし、それらを処理し、結果を.NETに返す機能を追加しました。 これがどのように機能するかの簡単な説明です 。
単一のマシンでも動作しますが、Redisインスタンスが必要です。 Redisはいくつかの信頼性保証を追加します-ペイロードは作業が完了を確認するまで保存されます。作業が終了した場合、ペイロードはジョブキューに返され、別のワーカーによって再処理されます。
WorkingDirectoryを設定するか、引数にpythonスクリプトの絶対パスを指定します
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:\\Python27\\python.exe";
//start.WorkingDirectory = @"D:\script";
start.Arguments = string.Format("D:\\script\\test.py -a {0} -b {1} ", "some param", "some other param");
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}