PTSV and calling python from C# - c#

is it possible to use python tools for visual studio in visual studio such that it allows for side by side coding of ASP.NET C# application and some python code?
Secondly how do i call a python script from C#?
Thanks in advance.

As for running python scripts in C# you can always do something like this:
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "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);
}
}
Passing python script as cmd and arguments as args.

Related

How to run python script from C# [duplicate]

This sort of question has been asked before in varying degrees, but I feel it has not been answered in a concise way and so I ask it again.
I want to run a script in Python. Let's say it's this:
if __name__ == '__main__':
with open(sys.argv[1], 'r') as f:
s = f.read()
print s
Which gets a file location, reads it, then prints its contents. Not so complicated.
Okay, so how do I run this in C#?
This is what I have now:
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);
}
}
}
When I pass the code.py location as cmd and the filename location as args it doesn't work. I was told I should pass python.exe as the cmd, and then code.py filename as the args.
I have been looking for a while now and can only find people suggesting to use IronPython or such. But there must be a way to call a Python script from C#.
Some clarification:
I need to run it from C#, I need to capture the output, and I can't use IronPython or anything else. Whatever hack you have will be fine.
P.S.: The actual Python code I'm running is much more complex than this, and it returns output which I need in C#, and the C# code will be constantly calling the Python code.
Pretend this is my code:
private void get_vals()
{
for (int i = 0; i < 100; i++)
{
run_cmd("code.py", i);
}
}
The reason it isn't working is because you have UseShellExecute = false.
If you don't use the shell, you will have to supply the complete path to the python executable as FileName, and build the Arguments string to supply both your script and the file you want to read.
Also note, that you can't RedirectStandardOutput unless UseShellExecute = false.
I'm not quite sure how the argument string should be formatted for python, but you will need something like this:
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);
}
}
}
If you're willing to use IronPython, you can execute scripts directly in C#:
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
private static void doPython()
{
ScriptEngine engine = Python.CreateEngine();
engine.ExecuteFile(#"test.py");
}
Get IronPython here.
Execute Python script from C
Create a C# project and write the following code.
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"
You will see the 'Python C# Test' in the console of C#.
I ran into the same problem and Master Morality's answer didn't do it for me. The following, which is based on the previous answer, worked:
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);
}
}
}
As an example, cmd would be #C:/Python26/python.exe and args would be C://Python26//test.py 100 if you wanted to execute test.py with cmd line argument 100. Note that the path the .py file does not have the # symbol.
Actually its pretty easy to make integration between Csharp (VS) and Python with IronPython. It's not that much complex... As Chris Dunaway already said in answer section I started to build this inegration for my own project. N its pretty simple.
Just follow these steps N you will get your results.
step 1 : Open VS and create new empty ConsoleApp project.
step 2 : Go to tools --> NuGet Package Manager --> Package Manager Console.
step 3 : After this open this link in your browser and copy the NuGet Command.
Link: https://www.nuget.org/packages/IronPython/2.7.9
step 4 : After opening the above link copy the PM>Install-Package IronPython -Version 2.7.9
command and paste it in NuGet Console in VS.
It will install the supportive packages.
step 5 : This is my code that I have used to run a .py file stored in my Python.exe
directory.
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
}
}
step 6 : save and execute the code
Set WorkingDirectory or specify the full path of the python script in the 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);
}
}
I am having problems with stdin/stout - when payload size exceeds several kilobytes it hangs. I need to call Python functions not only with some short arguments, but with a custom payload that could be big.
A while ago, I wrote a virtual actor library that allows to distribute task on different machines via Redis. To call Python code, I added functionality to listen for messages from Python, process them and return results back to .NET.
Here is a brief description of how it works.
It works on a single machine as well, but requires a Redis instance. Redis adds some reliability guarantees - payload is stored until a worked acknowledges completion. If a worked dies, the payload is returned to a job queue and then is reprocessed by another worker.
had same issure and this worked for me:
using IronPython.Hosting;
var engine = Python.CreateEngine();
engine.ExecuteFile("") //put the directory of the program in the quote marks

python pandas missing required dependencies 'numpy' in visual studio

I have anaconda3 installed on my Windows 10 machine.
I want to get the python script to run and return the results to C#.
So here is my code in C#:
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = #"C:\Users\John\AppData\Local\Cotinum\anaconda3\python.exe";
start.Arguments = string.Format("{0}", #"C:\test.py", "test");
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
using (StreamReader reader = process.StandardOutput)
{
string foo = reader.ReadToEnd();
TxtResultOutput.Text += foo;
}
The python code
import pandas as pd
import sys
def test_func(f_name):
a = pd.read_excel(f_name)
return a
if __name__ == "__main__":
f_name = sys.argv[1]
test_func(f_name)
When I run C# code, in the output window of Visual Studio. It shows the error:
File "C:\Users\John\AppData\Local\Continuum\anaconda3\lib\site-package\pandas__init__.py", line 19,
in module
"Missing required dependencies {0}".format(missing_dependencies))
ImportError: Missing required dependencies ['numpy']
However I don't believe I missed it because I can run the script from anaconda3 prompt window. It must be that somehow the PATH can't found in Visual Studio/ C# environment.

Activating conda environment from c# code (or what is the differences between manually opening cmd and opening it from c#?)

I want to run a gpu accelerated python script on windows using conda environment (dlwin36).
I’m trying to activate dlwin36 and execute a script:
1) activate dlwin36
2) set KERAS_BACKEND=tensorflow
3) python myscript.py
If I manually open cmd on my machine and write:"activate dlwin36"
it works.
But when I try opening a cmd from c# I get:
“activate is not recognized as an internal or external command, operable program or batch file.”
I tried using the following methods:
Command chaining:
var start = new ProcessStartInfo();
start.FileName = "cmd.exe";
start.Arguments = "/c activate dlwin36&&set KERAS_BACKEND=tensorflow&&python myscript.py";
Process.Start(start).WaitForExit();
(I’ve tested several variations of UseShellExecute, LoadUserProfile and WorkingDirectory)
Redirect standard input:
var commandsList = new List<string>();
commandsList.Add("activate dlwin36");
commandsList.Add("set KERAS_BACKEND=tensorflow");
commandsList.Add("python myscript.py");
var start = new ProcessStartInfo();
start.FileName = "cmd.exe";
start.UseShellExecute = false;
start.RedirectStandardInput = true;
var proc = Process.Start(start);
commandsList.ForEach(command => proc.StandardInput.WriteLine(command));
(I’ve tested several variations of LoadUserProfile and WorkingDirectory)
In both cases, I got the same error.
It seems that there is a difference between manually opening cmd and opening it from c#.
The key is to run activate.bat in your cmd.exe before doing anything else.
// Set working directory and create process
var workingDirectory = Path.GetFullPath("Scripts");
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
RedirectStandardInput = true,
UseShellExecute = false,
RedirectStandardOutput = true,
WorkingDirectory = workingDirectory
}
};
process.Start();
// Pass multiple commands to cmd.exe
using (var sw = process.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
// Vital to activate Anaconda
sw.WriteLine("C:\\PathToAnaconda\\anaconda3\\Scripts\\activate.bat");
// Activate your environment
sw.WriteLine("activate your-environment");
// Any other commands you want to run
sw.WriteLine("set KERAS_BACKEND=tensorflow");
// run your script. You can also pass in arguments
sw.WriteLine("python YourScript.py");
}
}
// read multiple output lines
while (!process.StandardOutput.EndOfStream)
{
var line = process.StandardOutput.ReadLine();
Console.WriteLine(line);
}
You need to use the python.exe from your environment. For example:
Process proc = new Process();
proc.StartInfo.FileName = #"C:\path-to-Anaconda3\envs\tensorflow-gpu\python.exe";
or in your case:
start.Arguments = "/c activate dlwin36&&set KERAS_BACKEND=tensorflow&&\"path-to-Anaconda3\envs\tensorflow-gpu\python.exe\" myscript.py";
I spent a bit of time working on this and here's the only thing that works for me: run a batch file that will activate the conda environment and then issue the commands in python, like so. Let's call this run_script.bat:
call C:\Path-to-Anaconda\Scripts\activate.bat myenv
set KERAS_BACKEND=tensorflow
python YourScript.py
exit
(Note the use of the call keyword before we invoke the activate batch file.)
After that you can run it from C# more or less as shown above.
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "cmd.exe";
start.Arguments = "/K c:\\path_to_batch\\run_script.bat";
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.WorkingDirectory = "c:\\path_to_batch";
string stdout, stderr;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
stdout = reader.ReadToEnd();
}
using (StreamReader reader = process.StandardError)
{
stderr = reader.ReadToEnd();
}
process.WaitForExit();
}
I am generating the batch file on the fly in C# to set the necessary parameters.
If this is gonna help anyone in the future. I found that you must run the activation from C:\ drive.

Unable to run python script in c# which runs scrapy spider

I followed this_link and I was able to run a dummy python file from my c# code like this...
public JsonResult FetchscrapyDataUrl(String website)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = #"C:\ProgramData\Anaconda3\python.exe";
start.Arguments = #"C:\Users\PycharmProjects\scraping_web\scrape_info\main.py";
//this is path to .py file from scrapy project
start.CreateNoWindow = false; // We don't need new window
start.UseShellExecute = false; // Do not use OS shell
//start.RedirectStandardOutput = true;// Any output, generated by application will be redirected back
start.RedirectStandardError = true; // Any error in standard output will be redirected back (for example exceptions)
Console.WriteLine("Python Starting");
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string stderr = process.StandardError.ReadToEnd(); // Here are the exceptions from our Python script
string result = reader.ReadToEnd(); // Here is the result of StdOut(for example: print "test")
Console.Write(result);
}
}
}
Now I know that I can run scrapy spider from a single file main.py like this...
from scrapy import cmdline
cmdline.execute("scrapy crawl text".split())
When I run main.py file from cmd in windows it works fine but it does not work when I run it from C# code .Net framework. The error is ...
"Scrapy 1.4.0 - no active project\r\n\r\nUnknown command: crawl\r\n\r\nUse \"scrapy\" to see available commands\r\n"
Any Idea how to run this...Or am i missing some path setting in windows ??
Or should I run my spider from C# in some other way??
You need to set the WorkingDirectory property
start.WorkingDirectory = #"C:\Users\PycharmProjects\scraping_web\scrape_info\"
Or you need to cd to that directory to make it work

Using C# 4.0 to run Python scripts error non-ascii char

I eventually want to be able to return a DataFrame from Python to C#. At the moment I am running a very simple console app to try and run a basic Python script. This script compiles and runs in Canopy fine however when I run it from C# I get the error relating to non-ASCII chars.
I have read many articles relating to this but none of them seem to resolve the issue I have.
Error
SyntaxError: Non-ASCII character '\x90' in file C:\Program Files\Enthought\Canop
y32\App\appdata\canopy-1.5.2.2785.win-x86\python.exe on line 1, but no encoding
declared; see http://www.python.org/peps/pep-0263.html for details
Thx in advance for any help!
static int test_python_canopy()
{
string cmd;
string args;
args = "C:\\Share\\Python\\test.py";
cmd = #"C:\Program Files\Enthought\Canopy32\App\appdata\canopy-1.5.2.2785.win-x86\python.exe";
cmd = "\"" + cmd + "\"";
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;
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);
}
}
return 0;
}
For ProcessStartInfo, FileName should be set to the executable that you wish to run and Arguments should be set to the arguments that you want to pass to that executable.
In your code, FileName is set correctly to the Python interpreter. Arguments, however, the first argument is being set to Python interpreter. The net result is that C# is trying to execute this command:
C:\Program Files\Enthought\Canopy32\App\appdata\canopy-1.5.2.2785.win-x86\python.exe C:\Program Files\Enthought\Canopy32\App\appdata\canopy-1.5.2.2785.win-x86\python.exe C:\Share\Python\test.py
which means that Python is trying to use the Python executable as a script, which is not going to work. Changing the line that sets the arguments should fix the problem:
start.Arguments = args;

Categories