Bagaimana cara menjalankan skrip Python dari C #?

130

Pertanyaan semacam ini telah diajukan sebelumnya dalam berbagai tingkat, tetapi saya merasa itu belum dijawab secara ringkas sehingga saya bertanya lagi.

Saya ingin menjalankan skrip dengan Python. Katakanlah ini:

if __name__ == '__main__':
    with open(sys.argv[1], 'r') as f:
        s = f.read()
    print s

Yang mendapat lokasi file, membacanya, lalu mencetak isinya. Tidak terlalu rumit.

Oke, jadi bagaimana cara menjalankan ini di C #?

Inilah yang saya miliki sekarang:

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

Ketika saya melewati code.pylokasi sebagai cmddan filenamelokasi karena argstidak berfungsi. Saya diberitahu bahwa saya harus lulus python.exesebagai cmd, dan kemudian code.py filenamesebagai args.

Saya telah mencari beberapa saat sekarang dan hanya dapat menemukan orang yang menyarankan untuk menggunakan IronPython atau semacamnya. Tetapi harus ada cara untuk memanggil skrip Python dari C #.

Beberapa klarifikasi:

Saya perlu menjalankannya dari C #, saya perlu menangkap output, dan saya tidak bisa menggunakan IronPython atau apa pun. Apapun hack yang Anda miliki akan baik-baik saja.

PS: Kode Python aktual yang saya jalankan jauh lebih kompleks dari ini, dan mengembalikan keluaran yang saya butuhkan di C #, dan kode C # akan terus-menerus memanggil kode Python.

Berpura-puralah ini kode saya:

    private void get_vals()
    {
        for (int i = 0; i < 100; i++)
        {
            run_cmd("code.py", i);
        }
    }
Inbar Rose
sumber
1
Apakah kode C # harus memanggil skrip Python atau tidak apa-apa jika (seperti yang Anda nyatakan di akhir) Anda hanya memanggil juru bahasa python yang kemudian menjalankan skrip?
Gerald Versluis
1
Apakah Anda diizinkan menggunakan IronPython?
Eugene
1
@GeraldVerslu tidak apa-apa, saya hanya perlu bisa menjalankannya melalui c # dan menangkap output.
Inbar Rose

Jawaban:

123

Alasan mengapa hal itu tidak berhasil adalah karena Anda memilikinya UseShellExecute = false.

Jika Anda tidak menggunakan shell, Anda harus menyediakan path lengkap ke python executable as FileName, dan membangun Argumentsstring untuk memasok skrip dan file yang ingin Anda baca.

Perhatikan juga, bahwa Anda tidak bisa RedirectStandardOutputkecuali UseShellExecute = false.

Saya tidak yakin bagaimana string argumen harus diformat untuk python, tetapi Anda akan membutuhkan sesuatu seperti ini:

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);
         }
     }
}
Master Moralitas
sumber
saya ingin dapat mengambil output ke program saya untuk digunakan nanti. jadi saya harus memiliki shellexecute sebagai false. Anda mengatakan jika saya lulus c:\python26\python.exesebagai cmddan kemudian c:\temp\code.py c:\temp\testfile.txtsebagaimana argsmestinya bekerja?
Inbar Rose
Saya memperbarui dengan contoh cepat, saya mengalami masalah yang sama ketika saya melakukan sesuatu yang mirip dengan simpul
Master Morality
oke, itu bekerja untuk saya sekarang. masalahnya adalah Anda perlu memformat string dengan sangat hati-hati. jalan apa pun perlu "PATH"walaupun tidak ada spasi ... aneh ...
Inbar Rose
Milikku bekerja tanpa menyediakan jalan penuh. Saya mengatur UseShellExecuteke falsedan RedirectStandardOutputke true.
Nikhil Girraj
1
Bekerja tanpa menyediakan jalur jika installer Python diberitahu untuk menambahkan direktori Python ke PATH variabel lingkungan (sistem atau pengguna tertentu).
Manfred
59

Jika Anda ingin menggunakan IronPython, Anda dapat menjalankan skrip langsung di C #:

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

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

Dapatkan IronPython di sini.

Chris Dunaway
sumber
3
jelaskan ini kepada saya, dapatkah saya melakukan ini tanpa harus mengunduh apa pun? c # siap dengan plugin ini? juga - dapatkah saya menjalankan skrip eksternal dengan ini?
Inbar Rose
Anda harus menginstal IronPython, yang merupakan open source. Saya telah memperbarui jawabannya.
Chris Dunaway
7
perhatikan bahwa IronPython dan Python tidak persis sama. Sebagai catatan ...
Ron Klein
1
IronPython tampaknya tidak mendukung serangkaian fitur bahasa yang sama dengan Python 3.6.x. Oleh karena itu IronPython hanya merupakan opsi jika Anda tidak menggunakan salah satu fitur bahasa tersebut. Tapi ini pasti patut dicoba.
Manfred
1
@RonKlein, mereka tidak sama, dan jika Anda mencoba menggunakan perpustakaan seperti scikit-learn (untuk tujuan ML), itu tidak akan bekerja untuk Anda juga
moarra
28

Jalankan skrip Python dari C

Buat proyek C # dan tulis kode berikut.

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

cetak "Python C # Test"

Anda akan melihat 'Python C # Test' di konsol C #.

Rohit Salunke
sumber
Saya memiliki file skrip python di folder Windows seperti C:\Users\Documents\Visual Studio 2019. Karena ruang di path folder, itu diperlakukan sebagai pembatas args, jadi saya mendapatkan fileNametidak dapat ditemukan. Apakah ada cara untuk keluar dari ruang?
Leon Chang
15

Saya mengalami masalah yang sama dan jawaban Guru Moralitas tidak melakukannya untuk saya. Berikut ini, yang didasarkan pada jawaban sebelumnya, berfungsi:

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

Sebagai contoh, cmd akan menjadi @C:/Python26/python.exedan args akan C://Python26//test.py 100jika Anda ingin menjalankan test.py dengan argumen garis cmd 100. Perhatikan bahwa path file .py tidak memiliki simbol @.

Derek
sumber
2
Dapatkah seseorang mengomentari mengapa ini -1. Apakah ada yang salah.
Keith Loughnane
2
Persis sama dengan jawaban di atas hanya Anda menetapkan FileName dari parameter saja. Tetapi pada akhirnya startmemiliki nilai yang sama
sarang
4

Hanya juga untuk menarik perhatian Anda pada ini:

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

Ini bekerja dengan baik.

cs0815
sumber
Hei, aku sudah mencoba ini dan kelihatannya berhasil. Tapi saya mendapatkan kesalahan di modul impor. seperti cv2. tulisannya tidak ada modul bernama cv2. Bagaimana saya dapat memecahkan ini apakah Anda punya ide
İsa GİRİŞKEN
3
Tautan ini sekarang dialihkan ke daftar topik. Hanya satu yang menyebutkan Python dan itu tidak terlalu relevan.
Greg Vogel
3

Atur WorkingDirectory atau tentukan path lengkap skrip python di Argument

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);
    }
}
LIU YUE
sumber
3

Sebenarnya cukup mudah untuk melakukan integrasi antara Csharp (VS) dan Python dengan IronPython. Ini tidak terlalu rumit ... Seperti yang sudah dikatakan Chris Dunaway di bagian jawaban, saya mulai membangun inegrasi ini untuk proyek saya sendiri. Cukup sederhana. Cukup ikuti langkah-langkah ini N Anda akan mendapatkan hasil Anda.

langkah 1: Buka VS dan buat proyek ConsoleApp kosong yang baru.

langkah 2: Buka alat -> NuGet Package Manager -> Package Manager Console.

langkah 3: Setelah ini buka tautan ini di browser Anda dan salin NuGet Command. Tautan: https://www.nuget.org/packages/IronPython/2.7.9

langkah 4: Setelah membuka tautan di atas, salin perintah PM> Install-Package IronPython -Version 2.7.9 dan tempel di NuGet Console di VS. Ini akan menginstal paket yang mendukung.

langkah 5: Ini adalah kode saya yang telah saya gunakan untuk menjalankan file .py yang disimpan di direktori Python.exe saya.

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

langkah 6: simpan dan jalankan kode

Daulmalik
sumber
Sebagai seorang pengembang saya tidak memilih solusi karena itu "mudah" untuk diterapkan. Saya memilih satu yang melakukan pekerjaan. IronPython hanya diporting ke python 2.7 dan bekerja pada python 3 sedang berlangsung selama beberapa tahun sekarang, tanpa akhir yang terlihat. Semoga kode python Anda ada di versi yang benar.
peter.cyc
per 27 april 2020: github.com/IronLanguages/ironpython2/releases/tag/ipy-2.7.10 , tapi masih belum python 3.
Luuk
0

Saya mengalami masalah dengan stdin/stout- ketika ukuran muatan melebihi beberapa kilobyte itu hang. Saya perlu memanggil fungsi Python tidak hanya dengan beberapa argumen pendek, tetapi dengan payload kustom yang bisa jadi besar.

Beberapa waktu yang lalu, saya menulis perpustakaan aktor virtual yang memungkinkan untuk mendistribusikan tugas pada mesin yang berbeda melalui Redis. Untuk memanggil kode Python, saya menambahkan fungsionalitas untuk mendengarkan pesan dari Python, memprosesnya dan mengembalikan hasilnya ke .NET. Berikut ini adalah deskripsi singkat tentang cara kerjanya .

Ini bekerja pada satu mesin juga, tetapi membutuhkan contoh Redis. Redis menambahkan beberapa jaminan keandalan - muatan disimpan sampai karya berhasil diselesaikan. Jika seorang pekerja meninggal, payload dikembalikan ke antrian pekerjaan dan kemudian diproses kembali oleh pekerja lain.

VB
sumber
Mengapa Anda tidak menggunakan file keluar-masuk saja? alih-alih meminta pipa menangani semua pekerjaan itu.
Inbar Rose
@InbarRose Saya sudah memiliki sistem untuk .NET, jadi menambahkan pemrosesan Python sangat mudah dan saya masih memiliki distribusi dan keandalan - misalnya saya dapat mengirim muatan dari mesin Windows dan memprosesnya dari mesin Linux - file tidak akan berfungsi dalam hal ini kasus.
VB
@InbarRose Dan ketika payload sangat besar, saya bisa memberikan nama file pada mesin yang sama atau referensi S3 pada AWS, dll ...
VB