C # 'dan bir Python komut dosyasını nasıl çalıştırırım?


131

Bu tür bir soru daha önce çeşitli derecelerde sorulmuştu, ancak kısa bir şekilde yanıtlanmadığını hissediyorum ve bu yüzden tekrar soruyorum.

Python'da bir komut dosyası çalıştırmak istiyorum. Diyelim ki bu:

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

Dosya konumu alır, okur ve ardından içeriğini yazdırır. O kadar karmaşık değil.

Tamam, peki bunu C # 'da nasıl çalıştırırım?

Şu an sahip olduğum şey bu:

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

Ben geçtikten sonra code.pyolarak yerini cmdve filenamekonum olarak argsçalışmıyor. Ben geçmelidir söylendi python.exeolarak cmdve daha sonra, code.py filenamesıra args.

Bir süredir arıyordum ve sadece IronPython veya benzeri kullanmayı öneren kişileri bulabiliyorum. Ancak C # 'dan bir Python betiğini çağırmanın bir yolu olmalı.

Bazı açıklamalar:

C # üzerinden çalıştırmam gerekiyor, çıktıyı yakalamam gerekiyor ve IronPython veya başka bir şey kullanamıyorum. Sahip olduğunuz hack ne olursa olsun iyi olacak.

Not: Çalıştırdığım gerçek Python kodu bundan çok daha karmaşık ve C # 'da ihtiyacım olan çıktıyı döndürüyor ve C # kodu sürekli olarak Python kodunu çağırıyor olacak.

Bunun benim kodum olduğunu farz et:

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

1
C # kodunun Python betiğini çağırması gerekiyor mu yoksa (sonunda belirttiğiniz gibi) sadece daha sonra betiği çalıştıran python yorumlayıcısını çağırırsanız sorun olur mu?
Gerald Versluis

1
IronPython kullanma izniniz var mı?
Eugene

1
@GeraldVersluis tamam, sadece c # ile çalıştırıp çıktıyı yakalayabilmem gerekiyor.
Inbar Gül

Yanıtlar:


124

Çalışmamasının nedeni, sahip olmanızdır UseShellExecute = false.

Kabuğu kullanmazsanız, python çalıştırılabilirinin tam yolunu olarak sağlamanız ve hem komut dosyanızı hem de okumak istediğiniz dosyayı sağlayacak dizeyi FileNameoluşturmanız gerekir Arguments.

Ayrıca, RedirectStandardOutputsürece yapamayacağınızı unutmayın UseShellExecute = false.

Argüman dizesinin python için nasıl biçimlendirilmesi gerektiğinden tam olarak emin değilim, ancak bunun gibi bir şeye ihtiyacınız olacak:

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

Çıktıyı daha sonra kullanılmak üzere programıma alabilmek istiyorum. bu yüzden shellexecute'a false olarak ihtiyacım var. i geçmesi halinde diyorsun c:\python26\python.exeolarak cmdve daha sonra c:\temp\code.py c:\temp\testfile.txtsıra argsçalışması gerekir?
Inbar Gül

Hızlı bir örnekle güncelledim, düğüm ile benzer bir şey yaptığımda aynı sorunla karşılaştım
Master Morality

tamam, şimdi benim için çalışıyor. sorun, dizeleri çok dikkatli bir şekilde biçimlendirmeniz gerektiğidir. "PATH"boşluk olmasa bile herhangi bir yola ihtiyaç var ... garip ...
Inbar Rose

Benimki tam yol sağlamadan çalışıyor. Ben kuruyorum UseShellExecuteiçin falseve RedirectStandardOutputiçin true.
Nikhil Girraj

1
Python yükleyicisine Python dizinini PATH ortam değişkenine (sistem veya kullanıcıya özel) eklemesi söylendiyse, yolu sağlamadan çalışır.
Manfred

59

IronPython'u kullanmak istiyorsanız, komut dosyalarını doğrudan C # ile çalıştırabilirsiniz:

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

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

IronPython'u buradan edinin.


3
bunu bana açıkla, bunu hiçbir şey indirmeden yapabilir miyim? c # bu eklentiyle hazır mı geliyor? ayrıca - bununla harici komut dosyaları çalıştırabilir miyim?
Inbar Gül

Açık kaynak olan IronPython'u kurmanız gerekir. Cevabı güncelledim.
Chris Dunaway

7
IronPython ve Python'un tam olarak aynı şey olmadığını unutmayın. Sadece kayıt için ...
Ron Klein

1
IronPython, Python 3.6.x ile aynı dil özelliklerini desteklemiyor gibi görünüyor. Bu nedenle, IronPython yalnızca bu dil özelliklerinden herhangi birini kullanmıyorsanız bir seçenektir. Yine de kesinlikle denemeye değer.
Manfred

1
@RonKlein, aynı değiller ve scikit-learn (makine öğrenimi amaçlı) gibi bir kitaplık kullanmaya çalışıyorsanız, sizin için de işe yaramaz
moarra

28

C'den Python betiğini yürütün

Bir C # projesi oluşturun ve aşağıdaki kodu yazın.

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 # Testi" yazdır

C # konsolunda 'Python C # Testi'ni göreceksiniz .


Gibi bir Windows klasöründe bir python komut dosyası var C:\Users\Documents\Visual Studio 2019. Klasör yolundaki boşluk nedeniyle bağımsız değişken sınırlayıcı olarak kabul edilir, bu yüzden fileNamebulunamıyor. Uzaydan kaçmanın bir yolu var mı?
Leon Chang

15

Ben de aynı problemle karşılaştım ve Üstat Ahlak'ın cevabı benim için yapmadı. Önceki cevaba dayanan aşağıdakiler işe yaradı:

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

Örnek olarak, test.py'yi cmd satır bağımsız değişkeni 100 ile çalıştırmak istiyorsanız , cmd olacaktır @C:/Python26/python.exeve args olacaktır C://Python26//test.py 100. .Py dosyasının yolunun @ sembolüne sahip olmadığına dikkat edin.


2
Birisi bunun neden -1 olduğu hakkında yorum yapabilir mi? Bunun nesi var.
Keith Loughnane

2
Bunun yerine bir parametreden DosyaAdı atamanız yukarıdaki yanıtla tamamen aynıdır. Ama sonunda startaynı değerlere sahip
yuva


3

WorkingDirectory'yi ayarlayın veya bağımsız değişkendeki python betiğinin tam yolunu belirtin

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

Aslında Csharp (VS) ve IronPython ile Python arasında entegrasyon yapmak oldukça kolaydır. O kadar karmaşık değil ... Chris Dunaway'in cevap bölümünde söylediği gibi, bu inegrasyonu kendi projem için inşa etmeye başladım. N oldukça basit. Sadece şu adımları izleyin N sonuçlarınızı alacaksınız.

1. adım: VS'yi açın ve yeni boş ConsoleApp projesi oluşturun.

adım 2: Araçlar -> NuGet Paket Yöneticisi -> Paket Yöneticisi Konsolu'na gidin.

Adım 3: Bundan sonra tarayıcınızda bu bağlantıyı açın ve NuGet Komutunu kopyalayın. Bağlantı: https://www.nuget.org/packages/IronPython/2.7.9

adım 4: Yukarıdaki bağlantıyı açtıktan sonra PM> Install-Package IronPython -Version 2.7.9 komutunu kopyalayın ve VS'deki NuGet Konsoluna yapıştırın. Destekleyici paketleri kuracaktır.

Adım 5: Bu, Python.exe dizinimde depolanan bir .py dosyasını çalıştırmak için kullandığım kodum.

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. adım: kodu kaydedin ve yürütün


Bir geliştirici olarak bir çözüm seçmiyorum çünkü uygulaması "kolay". İşi yapan birini seçiyorum. IronPython yalnızca python 2.7'ye taşındı ve python 3 üzerinde çalışma, sonu görünmeden birkaç yıldır devam ediyor. Python kodunuzun doğru sürümde olduğunu umuyoruz.
peter.cyc

27 nisan 2020 itibariyle: github.com/IronLanguages/ironpython2/releases/tag/ipy-2.7.10 , ancak python 3 değil.
Luuk

0

Sorun yaşıyorum stdin/stout- yük boyutu birkaç kilobaytı aştığında askıda kalıyor. Python işlevlerini sadece bazı kısa argümanlarla değil, büyük olabilecek özel bir yük ile çağırmam gerekiyor.

Bir süre önce, Redis aracılığıyla farklı makinelerde görev dağıtılmasına izin veren sanal bir aktör kitaplığı yazmıştım. Python kodunu çağırmak için, Python'dan gelen mesajları dinlemek, işlemek ve sonuçları .NET'e geri döndürmek için işlevsellik ekledim. İşte nasıl çalıştığına dair kısa bir açıklama .

Tek bir makinede de çalışır, ancak bir Redis örneği gerektirir. Redis, bazı güvenilirlik garantileri ekler - işlenen bir onaylama tamamlanana kadar yük depolanır. Çalışılan bir ölürse, yük bir iş kuyruğuna döndürülür ve ardından başka bir çalışan tarafından yeniden işlenir.


Neden sadece giriş-çıkış dosyalarını kullanmıyorsun? boruların tüm bu işi halletmesi yerine.
Inbar Rose

@InbarRose Zaten .NET için sistemim vardı, bu yüzden Python işlemeyi eklemek çok kolaydı ve hala dağıtım ve güvenilirliğe sahibim - örneğin, bir Windows makinesinden yük gönderebilir ve onu bir Linux makinesinden işleyebilirim - dosyalar bunda çalışmaz durum.
VB

@InbarRose Ve yük gerçekten büyük olduğunda, aynı makinede bir dosya adı veya AWS'de S3 referansı vb.
VB
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.