ฉันจะเรียกใช้สคริปต์ Python จาก C # ได้อย่างไร


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และfilenameตำแหน่งเนื่องจากargsไม่ทำงาน ฉันบอกว่าฉันควรจะผ่านpython.exeเป็นcmdแล้วเป็นcode.py filenameargs

ฉันได้รับการมองหาในขณะนี้และสามารถหาคนแนะนำให้ใช้ IronPython หรือเช่นนั้น แต่จะต้องมีวิธีเรียกสคริปต์ Python จาก C #

ชี้แจงบางส่วน:

ฉันต้องการเรียกใช้จาก 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 interpreter ซึ่งจะเรียกใช้สคริปต์หรือไม่
Gerald Versluis

1
คุณได้รับอนุญาตให้ใช้ IronPython หรือไม่
ยูจีน

1
@ GeraldVersluis มันโอเคฉันแค่ต้องสามารถรันมันผ่าน c # และจับเอาท์พุท
Inbar Rose

คำตอบ:


123

UseShellExecute = falseเหตุผลที่จะไม่ทำงานเป็นเพราะคุณมี

หากคุณไม่ได้ใช้เชลล์คุณจะต้องระบุพา ธ ที่สมบูรณ์ไปยัง python ที่สามารถเรียกใช้FileNameงานได้และสร้างArgumentsสตริงเพื่อให้ทั้งสคริปต์และไฟล์ที่คุณต้องการอ่าน

นอกจากนี้ยังทราบว่าคุณไม่สามารถเว้นแต่RedirectStandardOutputUseShellExecute = false

ฉันไม่แน่ใจว่าวิธีการจัดรูปแบบสตริงอาร์กิวเมนต์สำหรับงูหลาม แต่คุณจะต้องมีสิ่งนี้:

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

ฉันต้องการที่จะนำเอาท์พุทไปยังโปรแกรมของฉันเพื่อใช้ในภายหลัง ดังนั้นฉันจำเป็นต้องมีที่พักพิงชั่วคราวว่าเป็นเท็จ คุณกำลังบอกว่าถ้าผมผ่านการc:\python26\python.exeเป็นcmdแล้วc:\temp\code.py c:\temp\testfile.txtเป็นargsมันควรจะทำงาน?
Inbar Rose

ฉันอัพเดทด้วยตัวอย่างรวดเร็วฉันพบปัญหาเดียวกันเมื่อฉันทำสิ่งที่คล้ายกับโหนด
Master Morality

โอเคมันใช้ได้สำหรับฉันแล้วตอนนี้ ปัญหาคือคุณต้องจัดรูปแบบสตริงอย่างระมัดระวัง เส้นทางใดก็ได้ที่ต้องการ"PATH"แม้ว่าจะไม่มีที่ว่าง ... แปลก ...
Inbar Rose

เหมืองทำงานโดยไม่ให้เส้นทางที่เต็ม ฉันกำลังตั้งค่าUseShellExecuteการfalseและการRedirectStandardOutput true
Nikhil Girraj

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 # มาพร้อมกับปลั๊กอินนี้หรือไม่ ด้วย - ฉันสามารถรันสคริปต์ภายนอกด้วยสิ่งนี้ได้หรือไม่
Inbar Rose

คุณจะต้องติดตั้ง IronPython ซึ่งเป็นโอเพ่นซอร์ส ฉันได้อัพเดตคำตอบแล้ว
Chris Dunaway

7
โปรดทราบว่า IronPython และ Python ไม่ใช่สิ่งเดียวกัน เพียงเพื่อบันทึก ...
Ron Klein

1
IronPython ดูเหมือนจะไม่รองรับคุณสมบัติภาษาชุดเดียวกับ Python 3.6.x ดังนั้น IronPython เป็นเพียงตัวเลือกหากคุณไม่ได้ใช้คุณสมบัติภาษาเหล่านั้น แต่ก็คุ้มค่าที่จะลอง
Manfred

1
@RonKlein พวกเขาจะไม่เหมือนกันและถ้าคุณกำลังพยายามที่จะใช้ห้องสมุดเช่น scikit การเรียนรู้ (สำหรับวัตถุประสงค์ ML) ก็จะไม่ทำงานสำหรับคุณทั้งสอง
moarra

28

รันสคริปต์ Python จาก C

สร้างโครงการ 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 # Test"

คุณจะเห็น'Python C # Test'ในคอนโซลของ C #


ฉันมีไฟล์สคริปต์หลามในโฟลเดอร์ Windows C:\Users\Documents\Visual Studio 2019เช่น เนื่องจากช่องว่างในโฟลเดอร์พา ธ จะถือว่าเป็นตัวคั่นของ args ดังนั้นฉันfileNameจึงไม่พบ มีวิธีหลบหนีอวกาศไหม?
Leon Chang

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 จะเป็น@C:/Python26/python.exeและ args จะเป็นC://Python26//test.py 100ถ้าคุณต้องการรัน test.py ด้วยอาร์กิวเมนต์บรรทัด cmd 100 โปรดทราบว่าเส้นทางที่ไฟล์. py ไม่มีสัญลักษณ์ @


2
บางคนสามารถแสดงความคิดเห็นได้ว่าทำไมถึงเป็น -1 มีอะไรผิดปกติกับมัน
Keith Loughnane

2
มันเหมือนกับคำตอบข้างต้นเพียงแค่กำหนด FileName ของคุณจากพารามิเตอร์แทน แต่ในตอนท้ายstartมีค่าเท่ากัน
ทำรัง

4

เพียงเพื่อดึงดูดความสนใจของคุณไปที่นี้:

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

มันใช้งานได้ดี


เฮ้ıลองทำสิ่งนี้และมันก็ใช้ได้ดี แต่ฉันได้รับข้อผิดพลาดที่โมดูลนำเข้า เช่นเดียวกับ cv2 มันเขียนไม่มีโมดูลชื่อ cv2 ฉันจะแก้ปัญหานี้ทำ u มีความคิดใด ๆ
İsaGİRİŞKEN

3
ลิงค์นี้จะเปลี่ยนเส้นทางไปยังรายการหัวข้อ มีเพียงหนึ่งไพ ธ อนที่กล่าวถึงเท่านั้นและมันไม่เกี่ยวข้องกันมาก
Greg Vogel

3

ตั้งค่า WorkingDirectory หรือระบุเส้นทางแบบเต็มของสคริปต์ไพ ธ อนในอาร์กิวเมนต์

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 มันไม่ซับซ้อนมากนัก ... อย่างที่ Chris Dunaway ได้กล่าวไว้ในหัวข้อคำตอบแล้วฉันเริ่มสร้างการรวมเข้าด้วยกันสำหรับโครงการของฉันเอง N มันค่อนข้างเรียบง่าย เพียงทำตามขั้นตอนเหล่านี้ N คุณจะได้รับผลลัพธ์

ขั้นตอนที่ 1: เปิด VS และสร้างโครงการ ConsoleApp ใหม่ที่ว่างเปล่า

ขั้นตอนที่ 2: ไปที่เครื่องมือ -> NuGet Package Manager -> Console Manager Package

ขั้นตอนที่ 3: หลังจากนี้เปิดลิงค์นี้ในเบราว์เซอร์ของคุณและคัดลอกคำสั่ง NuGet ลิงก์: https://www.nuget.org/packages/IronPython/2.7.9

ขั้นตอนที่ 4: หลังจากเปิดลิงค์ด้านบนให้คัดลอกคำสั่ง PM> Install-Package IronPython -Version 2.7.9 และวางไว้ใน NuGet Console ใน VS มันจะติดตั้งแพ็คเกจที่สนับสนุน

ขั้นตอนที่ 5: นี่คือรหัสของฉันที่ฉันใช้เพื่อเรียกใช้ไฟล์. py ที่เก็บไว้ในไดเรกทอรี Python.exe ของฉัน

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 อยู่ในช่วงสองสามปีที่ผ่านมา หวังว่าโค้ดไพ ธ อนของคุณจะเป็นเวอร์ชั่นที่ถูกต้อง
peter.cyc

ณ วันที่ 27 เมษายน 2020: github.com/IronLanguage/ironpython2/releases/tag/ipy-2.7.10แต่ก็ยังไม่ได้หลาม 3
Luuk

0

ฉันกำลังมีปัญหาstdin/stout- เมื่อขนาดของส่วนของข้อมูลเกินกว่าหลายกิโลไบต์มันจะหยุดทำงาน ฉันจำเป็นต้องเรียกใช้ฟังก์ชัน Python ไม่เพียง แต่มีอาร์กิวเมนต์สั้น ๆ เท่านั้น แต่ยังมีเพย์โหลดแบบกำหนดเองที่อาจใหญ่

เมื่อไม่นานมานี้ฉันได้เขียนห้องสมุดนักแสดงเสมือนที่อนุญาตให้เผยแพร่งานในเครื่องต่าง ๆ ผ่าน Redis ในการเรียกรหัส Python ฉันได้เพิ่มฟังก์ชันการทำงานเพื่อฟังข้อความจาก Python ประมวลผลและส่งคืนผลลัพธ์กลับไปเป็น. NET นี่คือคำอธิบายสั้น ๆ ว่ามันทำงานอย่างไร

มันทำงานบนเครื่องเดียวเช่นกัน แต่ต้องใช้อินสแตนซ์ Redis Redis เพิ่มการรับประกันความน่าเชื่อถือบางอย่าง - ส่วนของข้อมูลจะถูกเก็บไว้จนกว่างานจะเสร็จสมบูรณ์ หากทำงานไม่ทำงาน payload จะถูกส่งคืนไปยังคิวงานและจะถูกประมวลผลอีกครั้งโดยผู้ปฏิบัติงานอื่น


ทำไมคุณไม่ลองใช้ไฟล์เข้า - ออก? แทนที่จะให้ท่อจัดการกับงานทั้งหมด
Inbar Rose

@InbarRose ฉันมีระบบสำหรับ. NET อยู่แล้วดังนั้นการเพิ่มการประมวลผลของ Python นั้นง่ายมากและฉันก็ยังมีการกระจายและความน่าเชื่อถือ - เช่นฉันสามารถโพสต์ payload จากเครื่อง Windows และประมวลผลจากเครื่อง Linux - ไฟล์ไม่ทำงาน กรณี.
VB

@InbarRose และเมื่อ payload มีขนาดใหญ่มากฉันสามารถส่งชื่อไฟล์ในเครื่องเดียวกันหรือการอ้างอิง S3 บน AWS ฯลฯ ...
VB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.