Как запустить Python script с С#?
Такого рода вопрос уже задавался в разной степени, но я чувствую, что на него не дан краткий ответ, и поэтому я задаю его еще раз.
Я хочу запустить скрипт на Python. Позвольте сказать это так:
if __name__ == '__main__':
with open(sys.argv[1], 'r') as f:
s = f.read()
print s
Который получает местоположение файла, читает его, затем печатает его содержимое. Не так сложно.
Хорошо, так как мне запустить это в С#?
Вот что у меня сейчас:
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
местоположение code.py
как cmd
а расположение filename
как args
оно не работает. Мне сказали, что я должен передать python.exe
в качестве cmd
, а затем code.py filename
в качестве args
.
Я давно искал и могу найти только людей, предлагающих использовать IronPython или что-то подобное. Но должен быть способ вызова скрипта Python из С#.
Некоторые уточнения:
Мне нужно запустить его из С#, мне нужно захватить вывод, и я не могу использовать IronPython или что-либо еще. Какой бы взлом у вас ни был, все будет хорошо.
PS: Фактический код Python, который я запускаю, гораздо более сложен, чем этот, и он возвращает вывод, который мне нужен в С#, и код С# будет постоянно вызывать Python.
Притворись, что это мой код:
private void get_vals()
{
for (int i = 0; i < 100; i++)
{
run_cmd("code.py", i);
}
}
Ответы
Ответ 1
Причина, по которой он не работает, состоит в том, что у вас есть UseShellExecute = false
.
Если вы не используете оболочку, вам нужно будет предоставить полный путь к исполняемому файлу python как FileName
и построить строку Arguments
, чтобы предоставить как ваш script, так и файл, который вы хотите прочитать.
Также обратите внимание, что вы не можете 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);
}
}
}
Ответ 2
Если вы хотите использовать IronPython, вы можете выполнять скрипты непосредственно на С#:
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
private static void doPython()
{
ScriptEngine engine = Python.CreateEngine();
engine.ExecuteFile(@"test.py");
}
Получить IronPython здесь.
Ответ 3
Выполнить Python script с 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
print "Python C# Test"
В консоли С# вы увидите "Тест Python С#" .
Ответ 4
Я столкнулся с той же проблемой, и ответ Мастера Морали не сделал этого для меня. Следующее, основанное на предыдущем ответе, работало:
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 не имеет символа @.
Ответ 5
Просто чтобы обратить ваше внимание на это:
https://code.msdn.microsoft.com/windowsdesktop/C-and-Python-interprocess-171378ee
Работает отлично.
Ответ 6
У меня возникают проблемы с stdin/stout
- когда размер полезной нагрузки превышает несколько килобайт, которые он висит. Мне нужно вызвать функции Python не только с некоторыми короткими аргументами, но и с пользовательской полезной нагрузкой, которая может быть большой.
Некоторое время назад я написал виртуальную актерскую библиотеку, которая позволяет распределять задачу на разных машинах через Redis. Чтобы вызвать код Python, я добавил функциональность, чтобы прослушивать сообщения с Python, обрабатывать их и возвращать результаты обратно в .NET.
Вот краткое описание того, как это работает.
Он работает и на одной машине, но требует экземпляр Redis. Redis добавляет некоторые гарантии надежности - полезная нагрузка сохраняется до тех пор, пока работающий не подтвердит завершение. Если работающий умирает, полезная нагрузка возвращается в очередь заданий, а затем перерабатывается другим работником.
Ответ 7
Установите 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);
}
}
Ответ 8
На самом деле его легко сделать интеграцией между Csharp (VS) и Python с IronPython. Это не так уж сложно. Как уже сказал Крис Данэуэй в разделе ответов, я начал строить эту интеграцию для своего собственного проекта. N его преты просты. Просто следуйте этим шагам 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 и вставьте ее в консоль NuGet в 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: сохранить и выполнить код