Làm cách nào để chạy tập lệnh Python từ C #?


130

Loại câu hỏi này đã được hỏi trước đây ở các mức độ khác nhau, nhưng tôi cảm thấy nó chưa được trả lời một cách súc tích và vì vậy tôi hỏi lại.

Tôi muốn chạy một kịch bản trong Python. Hãy nói rằng đây là:

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

Mà có được một vị trí tập tin, đọc nó, sau đó in nội dung của nó. Không quá phức tạp.

Được rồi, vậy làm thế nào để tôi chạy cái này trong C #?

Đây là những gì tôi có bây giờ:

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

Khi tôi vượt qua code.pyvị trí cmdfilenamevị trí như argsnó không hoạt động. Tôi đã nói tôi nên vượt qua python.exenhư là cmd, và sau đó code.py filenameargs.

Tôi đã tìm kiếm một thời gian và chỉ có thể tìm thấy những người đề xuất sử dụng IronPython hoặc như vậy. Nhưng phải có cách gọi tập lệnh Python từ C #.

Một số làm rõ:

Tôi cần chạy nó từ C #, tôi cần nắm bắt đầu ra và tôi không thể sử dụng IronPython hoặc bất cứ thứ gì khác. Dù bạn có hack thì cũng sẽ ổn thôi.

PS: Mã Python thực tế tôi đang chạy phức tạp hơn nhiều so với mã này và nó trả về đầu ra mà tôi cần trong C # và mã C # sẽ liên tục gọi mã Python.

Giả vờ đây là mã của tôi:

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

1
Mã C # có phải gọi tập lệnh Python hay không, nếu nó (như bạn đã nêu ở cuối) bạn chỉ cần gọi trình thông dịch python để chạy tập lệnh?
Gerald Versluis

1
Bạn có được phép sử dụng IronPython không?
Eugene

1
@GeraldVersluis không sao, tôi chỉ cần có thể chạy nó qua c # và bắt đầu ra.
Inbar Rose

Câu trả lời:


123

Lý do nó không hoạt động là vì bạn có UseShellExecute = false.

Nếu bạn không sử dụng shell, bạn sẽ phải cung cấp đường dẫn đầy đủ cho python có thể thực thi được FileNamevà xây dựng Argumentschuỗi để cung cấp cả tập lệnh của bạn và tệp bạn muốn đọc.

Cũng lưu ý rằng bạn không thể RedirectStandardOutputtrừ khi UseShellExecute = false.

Tôi không chắc chắn làm thế nào chuỗi đối số nên được định dạng cho python, nhưng bạn sẽ cần một cái gì đó như thế này:

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

tôi muốn có thể đưa đầu ra cho chương trình của mình để sử dụng sau. Vì vậy, tôi cần phải có Shellexecute là sai. bạn đang nói nếu tôi vượt qua c:\python26\python.exenhư cmdvà sau đó c:\temp\code.py c:\temp\testfile.txtargsnó sẽ làm việc?
Inbar Rose

Tôi đã cập nhật với một ví dụ nhanh, tôi gặp vấn đề tương tự khi tôi làm điều gì đó tương tự với nút
Master Morality

được rồi, nó làm việc cho tôi bây giờ vấn đề là bạn cần định dạng các chuỗi rất cẩn thận. bất kỳ con đường nào cũng cần "PATH"ngay cả khi không có khoảng trống ... lạ ...
Inbar Rose

Tôi làm việc mà không cung cấp đường dẫn đầy đủ. Tôi đang thiết UseShellExecuteđể falseRedirectStandardOutputđể true.
Nikhil Girraj

1
Hoạt động mà không cung cấp đường dẫn nếu trình cài đặt Python được yêu cầu thêm thư mục Python vào biến môi trường PATH (hệ thống hoặc người dùng cụ thể).
Manfred

59

Nếu bạn sẵn sàng sử dụng IronPython, bạn có thể thực thi các tập lệnh trực tiếp trong C #:

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

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

Nhận IronPython ở đây.


3
giải thích cho tôi, tôi có thể làm điều này mà không phải tải xuống bất cứ điều gì không? c # đã sẵn sàng với plugin này? Ngoài ra - tôi có thể chạy các kịch bản bên ngoài với điều này?
Inbar Rose

Bạn sẽ phải cài đặt IronPython, đây là nguồn mở. Tôi đã cập nhật câu trả lời.
Chris Dunaway

7
lưu ý rằng IronPython và Python không hoàn toàn giống nhau. Chỉ để ghi lại ...
Ron Klein

1
IronPython dường như không hỗ trợ tập hợp các tính năng ngôn ngữ giống như Python 3.6.x. Do đó, IronPython chỉ là một tùy chọn nếu bạn không sử dụng bất kỳ tính năng ngôn ngữ nào. Nó chắc chắn đáng để thử, mặc dù.
Manfred

1
@RonKlein, chúng không giống nhau và nếu bạn đang cố sử dụng một thư viện như scikit-learn (cho mục đích ML), nó sẽ không hoạt động cho bạn
moarra

28

Thực thi tập lệnh Python từ C

Tạo một dự án C # và viết mã sau đây.

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 mẫu_script

in "Kiểm tra Python C #"

Bạn sẽ thấy 'Python C # Test' trong bảng điều khiển của C #.


Tôi có một tập tin python trong một thư mục Windows như thế nào C:\Users\Documents\Visual Studio 2019. Do không gian trong đường dẫn thư mục, nó được coi là dấu phân cách của args, vì vậy tôi nhận được fileNamekhông thể tìm thấy. Có cách nào để thoát khỏi không gian?
Leon Chang

15

Tôi gặp vấn đề tương tự và câu trả lời của Master Morality đã không làm điều đó cho tôi. Sau đây, dựa trên câu trả lời trước, đã hoạt động:

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

Ví dụ: cmd sẽ là @C:/Python26/python.exevà đối số sẽ là C://Python26//test.py 100nếu bạn muốn thực thi test.txt với đối số dòng cmd 100. Lưu ý rằng đường dẫn của tệp .py không có ký hiệu @.


2
Ai đó có thể nhận xét tại sao điều này là -1. Có gì sai với nó.
Keith Loughnane

2
Nó hoàn toàn giống với câu trả lời ở trên chỉ là gán Tên tệp của bạn từ một tham số thay thế. Nhưng cuối cùng startcũng có những giá trị tương tự
làm tổ vào

4

Cũng để thu hút sự chú ý của bạn về điều này:

https://code.msdn.microsoft.com/windowsdesktop/C-and-Python-inter process-173737ee

Nó hoạt động rất tốt.


Này, tôi đã thử cái này và nó có vẻ hoạt động tốt. Nhưng tôi nhận được lỗi tại các mô-đun nhập khẩu. như cv2. văn bản của nó không có mô-đun có tên cv2. Làm thế nào tôi có thể giải quyết điều này để bạn có bất kỳ ý tưởng nào
İsa GtubRtubŞKEN

3
Liên kết này bây giờ chuyển hướng đến danh sách các chủ đề. Chỉ có một đề cập đến Python và nó không liên quan lắm.
Greg Vogel

3

Đặt WorkDirectory hoặc chỉ định đường dẫn đầy đủ của tập lệnh python trong Đối số

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

Trên thực tế, việc tích hợp giữa Csharp (VS) và Python với IronPython khá dễ dàng. Nó không phức tạp lắm ... Như Chris Dunaway đã nói trong phần trả lời, tôi bắt đầu xây dựng sự xâm nhập này cho dự án của riêng mình. N nó khá đơn giản. Chỉ cần làm theo các bước N bạn sẽ nhận được kết quả của bạn.

Bước 1: Mở VS và tạo dự án ConsoleApp trống mới.

Bước 2: Chuyển đến công cụ -> Trình quản lý gói NuGet -> Bảng điều khiển quản lý gói.

Bước 3: Sau khi mở liên kết này trong trình duyệt của bạn và sao chép Lệnh NuGet. Liên kết: https://www.nuget.org/packages/IronPython/2.7.9

Bước 4: Sau khi mở liên kết trên, sao chép lệnh PM> Cài đặt gói IronPython -Version 2.7.9 và dán nó vào NuGet Console trong VS. Nó sẽ cài đặt các gói hỗ trợ.

Bước 5: Đây là mã của tôi mà tôi đã sử dụng để chạy tệp .py được lưu trữ trong thư mục Python.exe của tôi.

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

Bước 6: lưu và thực thi mã


Là một nhà phát triển, tôi không chọn giải pháp vì nó "dễ thực hiện". Tôi chọn một trong đó làm công việc. IronPython chỉ được chuyển sang python 2.7 và hoạt động trên python 3 là điều tất nhiên trong một vài năm nay, mà không có kết thúc trước mắt. Hy vọng mã python của bạn là trong phiên bản phù hợp.
peter.cyc

kể từ ngày 27 tháng 4 năm 2020: github.com/IronLacular/ironpython2/release/tag/ipy-2.7.10 , nhưng vẫn không phải là trăn 3.
Luuk

0

Tôi đang gặp vấn đề với stdin/stout- khi kích thước tải trọng vượt quá vài kilobyte thì nó bị treo. Tôi cần gọi các hàm Python không chỉ với một số đối số ngắn, mà với tải trọng tùy chỉnh có thể lớn.

Cách đây một thời gian, tôi đã viết một thư viện diễn viên ảo cho phép phân phối tác vụ trên các máy khác nhau thông qua Redis. Để gọi mã Python, tôi đã thêm chức năng nghe tin nhắn từ Python, xử lý chúng và trả kết quả trở lại .NET. Dưới đây là một mô tả ngắn gọn về cách thức hoạt động .

Nó cũng hoạt động trên một máy duy nhất, nhưng yêu cầu một ví dụ Redis. Redis thêm một số đảm bảo độ tin cậy - tải trọng được lưu trữ cho đến khi hoàn thành công việc. Nếu một công việc bị chết, tải trọng được trả về hàng đợi công việc và sau đó được xử lý lại bởi một công nhân khác.


Tại sao bạn không sử dụng các tập tin vào? thay vì có các đường ống xử lý tất cả các công việc đó.
Inbar Rose

@InbarRose Tôi đã có hệ thống cho .NET, vì vậy việc thêm xử lý Python rất dễ dàng và tôi vẫn có phân phối và độ tin cậy - ví dụ: tôi có thể gửi tải trọng từ máy Windows và xử lý nó từ máy Linux - các tệp sẽ không hoạt động trong này trường hợp
VB

@InbarRose Và khi tải trọng thực sự lớn, tôi có thể chuyển tên tệp trên cùng một máy hoặc tham chiếu S3 trên AWS, v.v ...
VB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.