C#からPythonスクリプトを実行するにはどうすればよいですか?


130

この種の質問は以前にさまざまな程度で尋ねられましたが、簡潔な方法で答えられていないと感じているので、もう一度質問します。

Pythonでスクリプトを実行したい。これだとしましょう:

if __name__ == '__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と、として、次にとして渡す必要があると言われました。filenameargspython.execmdcode.py filenameargs

私はしばらく探していましたが、IronPythonなどの使用を提案している人しか見つかりません。ただし、C#からPythonスクリプトを呼び出す方法が必要です。

いくつかの明確化:

C#から実行する必要があり、出力をキャプチャする必要があります。IronPythonなどは使用できません。どんなハックでも大丈夫です。

PS:私が実行している実際のPythonコードはこれよりもはるかに複雑で、C#で必要な出力を返します。C#コードは常にPythonコードを呼び出します。

これが私のコードであるとしましょう:

    private void get_vals()
    {
        for (int i = 0; i < 100; i++)
        {
            run_cmd("code.py", i);
        }
    }

1
C#コードはPythonスクリプトを呼び出す必要がありますか、それとも(最後に述べたように)pythonインタープリターを呼び出してスクリプトを実行するだけでよいですか?
Gerald Versluis、2012

1
IronPythonの使用は許可されていますか?
ユージーン

1
@GeraldVersluisは大丈夫です。C#で実行して出力をキャッチできる必要があります。
インバーローズ

回答:


123

それが機能しない理由は、あなたが持っているからですUseShellExecute = false

シェルを使用しない場合は、Python実行可能ファイルへの完全なパスをとして提供しFileNameArguments文字列を作成して、スクリプトと読み取るファイルの両方を提供する必要があります。

また、でないRedirectStandardOutput限りできないことに注意してくださいUseShellExecute = false

引数の文字列を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);
         }
     }
}

出力をプログラムに取り込んで後で使用できるようにしたい。だから私は偽としてshellexecuteを持っている必要があります。私が合格した場合、あなたが言っているc:\python26\python.exe通りcmd、次にc:\temp\code.py c:\temp\testfile.txtとしてargsそれが動作するはず?
インバーローズ

私は簡単な例で更新しましたが、ノードで同様のことをしたときに同じ問題に遭遇しました
Master Morality

大丈夫、それは今私のために動作します。問題は、文字列を慎重にフォーマットする必要があることです。"PATH"スペースがない場合でもパスは必要です...奇妙な...
インバーローズ

私はフルパスを提供せずに動作します。私は設定していますUseShellExecutefalseしてRedirectStandardOutputまでtrue
Nikhil Girraj 2015年

1
PythonインストーラーがPythonディレクトリーを環境変数PATH(システムまたはユーザー固有)に追加するように指示された場合、パスを提供せずに機能します。
Manfred

59

IronPythonを使用する場合は、C#で直接スクリプトを実行できます。

using IronPython.Hosting;
using Microsoft.Scripting.Hosting;

private static void doPython()
{
    ScriptEngine engine = Python.CreateEngine();
    engine.ExecuteFile(@"test.py");
}

ここでIronPythonを入手してください。


3
これを私に説明してください、何もダウンロードせずにこれを行うことができますか?c#にはこのプラグインが付属していますか?また-これで外部スクリプトを実行できますか?
インバーローズ

オープンソースのIronPythonをインストールする必要があります。答えを更新しました。
Chris Dunaway、2012

7
IronPythonとPythonはまったく同じではないことに注意してください。記録のために...
ロンクライン

1
IronPythonは、Python 3.6.xと同じ言語機能のセットをサポートしていないようです。したがって、IronPythonは、これらの言語機能を使用しない場合のオプションにすぎません。ただし、ぜひ試してみる価値はあります。
Manfred

1
@RonKlein、それらは同じではありません。scikit-learnなどのライブラリを(MLの目的で)使用しようとしても機能しません
moarra

28

CからPythonスクリプトを実行する

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 sample_script

「Python C#テスト」を印刷します

あなたは、表示されます「PythonのC#のテスト」を C#のコンソールで。


のようなWindowsフォルダーにpythonスクリプトファイルがありますC:\Users\Documents\Visual Studio 2019。フォルダーパスにスペースがあるため、引数の区切り文字として扱われるため、fileNameが見つかりません。宇宙を脱出する方法はありますか?
レオンチャン

15

私は同じ問題に遭遇し、マスター道徳の答えは私のためにそれをしませんでした。前の回答に基づいた次のコードは機能しました。

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.exeargsになりC://Python26//test.py 100ます。.pyファイルのパスに@記号がないことに注意してください。


2
これが-1である理由について誰かがコメントできますか?どうしたの。
Keith Loughnane、2015

2
代わりに、パラメーターからFileNameを割り当てるだけで、上記の答えとまったく同じです。しかし、最後startには同じ値があります
ネスト

4

これにあなたの注意を引くだけでも:

https://code.msdn.microsoft.com/windowsdesktop/C-and-Python-interprocess-171378ee

それは素晴らしい働きをします。


ねえ、私はこれを試してみましたが、うまくいきます。しかし、インポートモジュールでエラーが発生します。cv2のように。cv2という名前のモジュールはありません。缶は、この問題を解決、私はどのようuは任意のアイデアを持っている
ISAGİRİŞKEN

3
このリンクはトピックのリストにリダイレクトされるようになりました。Pythonについて言及したのは1人だけであり、あまり関連性がありません。
Greg Vogel

3

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);
    }
}

3

実際、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:コードを保存して実行する


開発者としては、実装が「簡単」なので、ソリューションを選びません。私は仕事をするものを選びます。IronPythonはpython 2.7にのみ移植されており、Python 3での作業は数年前から順調に進んでおり、終わりは見えません。あなたのpythonコードが正しいバージョンであることを願っています。
peter.cyc

2020年4月27日現在:github.com/IronLanguages/ironpython2/releases/tag/ipy-2.7.10、ただしpython 3ではない
Luuk

0

stdin/stoutペイロードサイズが数キロバイトを超えるとハングするという問題があります。一部の短い引数だけでなく、大きくなる可能性のあるカスタムペイロードを使用してPython関数を呼び出す必要があります。

少し前に、Redisを介してさまざまなマシンにタスクを分散できる仮想アクターライブラリを作成しました。Pythonコードを呼び出すために、Pythonからのメッセージをリッスンし、処理して結果を.NETに返す機能を追加しました。 これがどのように機能するかの簡単な説明です

単一のマシンでも動作しますが、Redisインスタンスが必要です。Redisはいくつかの信頼性保証を追加します-作業者は完了を確認するまでペイロードが保存されます。正常に動作した場合、ペイロードはジョブキューに返され、別のワーカーによって再処理されます。


なぜ入出力ファイルを使用しないのですか?パイプにその作業のすべてを処理させる代わりに。
インバーローズ2016

@InbarRose私はすでに.NETのシステムを持っていたので、Python処理の追加は非常に簡単で、まだ配布と信頼性があります。たとえば、Windowsマシンからペイロードをポストし、Linuxマシンから処理することができます-ファイルはこれで機能しません場合。
2016

@InbarRoseそして、ペイロードが本当に大きい場合、同じマシンのファイル名やAWSのS3リファレンスなどを渡すことができます...
VB
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.