what are the best practices to use python in c# application? - c#

I have a requirement for using Python analytics into c# application.
To be precise: c# should call a python script and get the output back into c# application for further processing.
I have tried using IronPython as recommend by many.
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
engine.ExecuteFile(#"DemoPythonApplication\SentimentAnalysis.py", scope);
dynamic testFunction = scope.GetVariable("create_sentiment_analysis"); //calling a function from python script file
var result = testFunction(); //This function is returning a dynamic dictionary, which I can use in my c# code further
But the limitation with IronPython is, it is not providing support for many python libraries like pandas, numpy, nltk etc, These libraries are getting used in python scripts. (since we have a different team working on python I don't have control over them for using specific libraries.)
Another option i tried is to run the python process and calling the script
private static readonly string PythonLocation = #"Programs\Python\Python37\python.exe"; //Location of Python.exe
private static readonly string PythonScript = #"DemoPythonApplication\SentimentAnalysis.py"; //Location of Python Script
private static void ProcessInPython(int a, int b)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = PythonLocation;
start.Arguments = string.Format("{0} {1} {2}", PythonScript, a, b);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
var result = reader.ReadToEnd();
Console.Write(result);
}
}
}
There are limitations of using this approach though, I am only able to get whatever is getting printed on the console as a string, and could not get the output that python functions are returning.
Also if I use the 2nd approach, I don't know how to call a specific function from the python script file.
Can someone help with the best practices of using python in c# for this kind of situation?

Related

Unity - Running a Neural Network

I trained a model using PyTorch. In Unity, I am using a WebCamTexture to display a live video. How can I feed the webcam frames into the PyTorch model, then perform actions in Unity with the output of the model?
I found Unity ML-agents, but it doesn't seem like it would help with this situation.
You can capture cam data on each update, then run your pytorch model by feeding it the data you just captured. I haven't tried and not sure how pytorch works, but for generic python scripts you can do something like:
...
void Start()
{
...
data = new Color32[webcamTexture.width * webcamTexture.height];
...
}
...
void FixedUpdate ()
{
...
webCamTexture.GetPixels32(data); //this is faster than returning a Color32 object
...
}
...
private void runPython(string pathToPythonExecutable, string pyTorchScript, Color32[] data)
{
var startInfo = new ProcessStartInfo();
var pyTorchArgs = convertDataToYourPyTorchInputFormat (data)
startInfo.Arguments = string.Format("{0} {1}", pyTorchScript, pyTorchArgs);
startInfo.FileName = pathToPythonExecutable;
startInfo.UseShellExecute = false;
var process = Process.Start(start));
process.WaitForExit();
//do stuff in unity with the return value of process (process.ExitCode) or whatever.
}
Mind you, this may create significant overhead to create and end processes using an external executable file. There are some libraries that allow you to run python scripts inside c#. I can think of 2: IronPython (http://ironpython.net) and Python for .Net (http://pythonnet.github.io) I have never tried them though.

What would be the best solution to send data between Python and C#?

I'm currently working on a C# application that needs to take advantage of the python NLP library, "spaCy", to parse text into data (Dict/JSON) that can be used on C# application
The application currently runs the python script with a unique id as a parameter, python finds the a txt file to parse on the disk using the id as the filename, does it's thing.. (parse into object) then returns the id to the C#.
I'd like to avoid saving to disk if possible.
public string parse(string s)
{
process.Arguments = pythonscript + " " + s; //pythonscript = python script name, s = location of txt file to parse
Process p = new Process();
p.StartInfo = process;
p.Start();
return ((StreamReader)p.StandardOutput).ReadToEnd().Replace(System.Environment.NewLine, ".json"); //json location
}

execute a python script in C#

I am trying to execute a python code in C#. Normally it should be done using IronPython and after installing PTVS (I'm using VS 2010).
var pyEngine = Python.CreateEngine();
var pyScope = pyEngine.CreateScope();
try
{
pyEngine.ExecuteFile("plot.py", pyScope);
}
catch (Exception ex)
{
Console.WriteLine("There is a problem in your Python code: " + ex.Message);
}
The problem is that it seems that IronPython doesn't recognize some libraries like numpy, pylab or matplotlib. I took a look a little bit and found some people talking about Enthought Canopy or Anaconda, which i have both installed without fixing the problem.
What should I do to get the problem solved?
In order to execute a Python script which imports some libraries such as numpy and pylab, it is possible to make this:
string arg = string.Format(#"C:\Users\ayed\Desktop\IronPythonExamples\RunExternalScript\plot.py"); // Path to the Python code
Process p = new Process();
p.StartInfo = new ProcessStartInfo(#"D:\WinPython\WinPython-64bit-2.7.5.3\python-2.7.5.amd64\python.exe", arg);
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true; // Hide the command line window
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.RedirectStandardError = false;
Process processChild = Process.Start(p.StartInfo);
If you execute your code, IronPython will only look for the script in the current working directory. You need to add some more search paths. This is a part of some old integration code in my application using ironpython:
var runtimeSetup = Python.CreateRuntimeSetup(null);
runtimeSetup.DebugMode = false;
runtimeSetup.Options["Frames"] = true;
runtimeSetup.Options["FullFrames"] = true;
var runtime = new ScriptRuntime(runtimeSetup);
var scriptEngine = runtime.GetEngineByTypeName(typeof(PythonContext).AssemblyQualifiedName);
// Set default search paths
ICollection<string> searchPaths = scriptEngine.GetSearchPaths();
searchPaths.Add("\\Scripts\\Python");
scriptEngine.SetSearchPaths(searchPaths);
The trick is to add all paths in this code line: scriptEngine.SetSearchPaths(searchPaths);. If you add the directory which contains plot.py here, all should work.
Hope this helps.

Invoking Astyle on a string or a file via C#

I am generating C++ code via C#, for some reason after applying astyle my generated code compiles. So is there a way I can invoke astyle from within my C# windows application?
Astyle is a command line tool, so using Process class you can call it externally and ask it to format the C++ source file.
I have done similar projects in the past, such as
http://alex.codeplex.com
I finally figured it out a few days ago, so thought i would share my function to astyle via c#
'
private void astyleDirectory(string target_path)
{
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
//Enter Path to get Astyle.exe here
pProcess.StartInfo.FileName=System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + #"\Astyle.exe";
pProcess.StartInfo.Arguments = "--options=none --style=ansi --recursive *.h *.cpp";
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.RedirectStandardError = true;
pProcess.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(target_path);
try
{
pProcess.Start();
string strOutput = pProcess.StandardOutput.ReadToEnd();
string strError = pProcess.StandardError.ReadToEnd();
pProcess.WaitForExit();
}
catch { }
}
'

Trying to pass stdin to a main method to evaluate code online

I am trying to build a web application to evaluate .Net code online (like http://ideone.com/)
I have managed to compile code with CodeDomProvider.
But I don't know how to pass stdin parameters to this function.
If a user writes this code in the textarea of my web application:
using System;
public class Test {
static void Main()
{
String t = "";
while (t != null){
t = Console.ReadLine();
Console.WriteLine(t+"OK");
}
}
}
I can Compile it with this code
CompilerInfo[] allCompilerInfo = CodeDomProvider.GetAllCompilerInfo();
//Tell the compiler what language was used
CodeDomProvider CodeProvider = CodeDomProvider.CreateProvider("C#");
//Set up our compiler options...
CompilerParameters CompilerOptions = new CompilerParameters();
var _with1 = CompilerOptions;
_with1.ReferencedAssemblies.Add("System.dll");
_with1.GenerateInMemory = true;
_with1.TreatWarningsAsErrors = true;
//Compile the code that is to be evaluated
CompilerResults Results = CodeProvider.CompileAssemblyFromSource(CompilerOptions, strCode);
Now I would like to manage generic parameters:
If I pass a sample parameter like this:
53
12
09
I would like the result of the compilation:
53OK
12OK
09OK
Do you know how to do this?
As I interpret the question, you are asking how to run and pass stdin command line data to an application that was compiled on your web server from code that a user typed into a text box. Avoiding the serious security concerns of doing such, what you want to do is launch the application using the System.Diagnostics.Process class, and specify RedirectStandardInput in the StartInfo property. Start by reading the MSDN docs on the Process class: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx

Categories