How to run C# Console Applications via Python? - python

I've created the following C# Console Application (.NET Core 3.1) with Visual Studio:
using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
//Check if args contains anything
if (args.Length > 0)
{
Console.WriteLine("args = " + args[0]);
} else
{
Console.WriteLine("args is empty");
}
//Prevent the application from closing itself without user input
string waiter = Console.ReadLine();
}
}
}
I am able to execute the application succesfully with one argument via cmd.exe:
CMD Input and Output
Now I'd like to run this program with one argument via Python. I've read How to execute a program or call a system command? and tried to implement it. However, it seems that the application is not being run properly.
The python code I am using via Jupyter notebook:
import subprocess
path = "C:/Users/duykh/source/repos/ConsoleApp2/ConsoleApp2/bin/Release/netcoreapp3.1/ConsoleApp2.exe"
subprocess.Popen(path) //#Also tried with .call and .run
//#subprocess.Popen([path, "argumentexample"]) doesn't work either
Output:
<subprocess.Popen at 0x2bcaeba49a0>
My question would be:
Why is it not being run (properly) and how do I properly run this application with one argument?

I've answered my own question. In a nutshell: I am pretty stupid.
Jupyter Notebook was running in the background and the application was being run there. That's why it didn't open a new prompt.
subprocess.Popen([path, "argument example"]) seems to work well for running a console application with an argument as input.

Related

Executing Python Script from Windows Forms .NET

I am fairly new to Python and .NET in general, but decided to ask more competent people, since I have been struggling with the issue of executing python script from Windows Forms.
The basic idea of my project is a desktop applicaton and the overall logic would be to read from a couple of selected check boxes, pass the values of those selections to my python script, from there I generate an excell table based on those results, and display this table back into the Windows Forms application.
Creating the table and managing to display it in the Desktop App is already done, but I am having serious issues with the communication between the two platforms, when it came to executing the script itself.
I have tried using IronPython and it worked perfectly, untill the fact that I found that Iron Python does not support CPython packages, like Pandas, which is build on numpy, and numpy apparantly is one of those packages. I looked over a lot of articles about this issue and the answers did not seem promising and most of the suggestions were to use pythonnet.
I tried to implement pythonnet, following numerous articles and all I managed to do, besides creating a bigger mess, is nothing as a result.
Finally, I decided to use C# Process class, but did not succeed also.
Would appreciate if there are any comments and suggestions on how to remedy this issue.
Python version: 3.7
Windows 10 (64 bit)
.NET Framework 4.7.2
Here is some of my code attempts in Windows Forms:
Implementation with the usage of the Process Class
Issue here is that I am not able to run this script due to the error messages that it cannot find the packages for the python script
var processStartInfo = new ProcessStartInfo
{
Arguments = "C:\\Users\\Dobromir\\PycharmProjects\\pythonProject\\main.py",
FileName = "C:\\Python27\\python.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
Process.Start(processStartInfo);
Implementation using IronPython (which was working before the usage of pandas package)
Issue here is the CPython packages limitation and errors.
For IronPython I had to downgrade to Python 2.7 in order to work with it. For the rest of the examples I am using Python 3.7
ScriptEngine pythonEngine = Python.CreateEngine();
var searchPaths = pythonEngine.GetSearchPaths();
searchPaths.Add(#"C:\Python27\Lib");
searchPaths.Add(#"C:\Users\Dobromir\PycharmProjects\pythonProject\venv\Lib\site-packages");
pythonEngine.SetSearchPaths(searchPaths);
List<String> argv = new List<String>();
argv.Add("Some Value1");
argv.Add("Some Value2");
ScriptSource pythonScript = pythonEngine.CreateScriptSourceFromFile("C:\\Users\\Dobromir\\PycharmProjects\\pythonProject\\main.py");
pythonEngine.GetSysModule().SetVariable("argv", argv);
pythonEngine.SetSearchPaths(searchPaths);
ScriptScope scope = pythonEngine.CreateScope();
pythonScript.Execute(scope);
Implementation of pythonnet
The issue that I got here is on the line using Py.GIL(). I believe it is having trouble finding the python files, and also tried giving the python37.dll in the variable pathToPython.
I received the error that Python.Runtime, Version=2.5.2.0, Culture=neutral....missmatch"
string pathToPython = #"C:\Users\Dobromir\AppData\Local\Programs\Python\Python37";
string path = pathToPython + "; " + Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);
Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONHOME", pathToPython, EnvironmentVariableTarget.Process);
Console.WriteLine(path);
var lib = new[]
{
#"C:\\Users\\Dobromir\\PycharmProjects\\App37\\main.py",
Path.Combine(pathToPython, "Lib"),
Path.Combine(pathToPython, "DLLs")
};
string paths = string.Join("; ", lib);
Environment.SetEnvironmentVariable("PYTHONPATH", paths, EnvironmentVariableTarget.Process);
using (Py.GIL()) //Initialize the Python engine and acquire the interpreter lock
{
try
{
Console.WriteLine("I am working");
}
catch (PythonException error)
{
Console.WriteLine("Error occured: ", error.Message);
}
}
I Also tried creating a bash script to execute the python script and got the no module found error as well
I know that these are not the best implementations out there, but do the job.
My question is if someone has any idea on how to make this simple operation work I would be very grateful, thank you for your time and understanding
P.S - Apologies for the long post, wanted to write what I have tried before asking for help, but if someone is more interested I will provide additional information.
I did a project like this recently; a couple of things I would suggest to make it easy:
Confirm that the instance of python set in your env variables (WIN+R, sysdm.cpl, Advanced, env variables) is that of the instance of python you wish to use (do this for your python search path too!)
Remove any lines attempting to set these in code; and instead handle errors if they are not found
Then, when you call you script from within your program; it only needs to look like this:
var processStartInfo = new ProcessStartInfo
{
Arguments = "main.py",
FileName = "Python",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
Process.Start(processStartInfo);
After some struggle, I found a solution to fit my needs.
Firstly, I completely removed python 2.7 and installed back 3.10.
I tried running the script file inside the shell command line and got the same error that the modules could not be found. What I did is try to import these modules and it gave an error, specifically for bs4 that I am using packages for python 2.x instead of 3.x packages.
After futher investigation I discovered that the packages that I have for my script are treated as "local" packages, meaning I installed them from the IDE (PyCharm) and they work for that project only I guess.
I also found that to "globally" access these packages I had to install them through the command line using the pip3 install <package_name>. After doing this the problem was gone and was left with running the script from the Windows Forms.
NOTE: I did not manage to start the script using python.exe, so I used bash script for the job.
Here is my code and I hope it helps someone down the line...
Code in C#
string myApp = string.Format("{0} {1}", #"C:\testing1.sh", "Hello");
var processStartInfo = new ProcessStartInfo
{
Arguments = myApp,
FileName = "C:\\Program Files\\Git\\git-bash.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = false
};
Process.Start(processStartInfo)
Code in Bash Script File
#!/bin/bash
arg1="$1"
python C:/Users/Dobromir/PycharmProjects/testing/main.py "$arg1"
Inside the Python file I am using sys.argv[] and accessing the arguments.
NOTE: Passing arguments from the bash script to the python script, in this case, you will receive 2 arguments - first one is the path to the python file and the second is the variable arg1.
Another important thing to mention is you need to have comas around the $1 - this is the property that is being send from the C# file, else it will show as empty.
Articles that were useful:
Installed BeautifulSoup but still get no module named bs4
Passing arguments to Python from Shell Script
https://unix.stackexchange.com/questions/31414/how-can-i-pass-a-command-line-argument-into-a-shell-script
https://gist.github.com/creativcoder/6df4d349447ff1416e68
Thank you to everyone who contributed and tried to help, I managed to learned new things with your suggestions!

Run java main class in command line/batch file/python script

I have a java class which is to be made into a tool so that I can give the input to the class as parameters and then produce the output in the command line, I have written the code in IntelliJ and want the code to be portable so that it can be used instantly by the click of a button. I have little experience in creating a bat file or python script.
package ase.ATool;
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class AnaliT {
public static void main(String[] args) {
File file = null;
File dir = new File(args[0]);
File[] directoryListing = dir.listFiles();
StringBuffer componentString = new StringBuffer(100);
if (directoryListing != null) {
for (File child : directoryListing) {
float complexity = 0, noOfMethods = 0;
System.out.println(child.getPath() + " ");
String currentLine;
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(child.getPath()));
System.out.println(bufferedReader);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
I want to convert the above code in to a tool so i can invoke this main function from the command line, batch file or python file.
You could compile and run the java file from python by checking out the subprocess module:
https://docs.python.org/3/library/subprocess.html
You can also run java code using the system module: running a java file in python using os.system()
If you want to invoke Java code from python, take a look here:
Calling Java from Python
Here it is recommended you use Py4J.
Here you can find an example of running a Java Class from a .bat file: How to run java application by .bat file
As mentioned in a comment you can also compile the file with java using java target.java and then run it with java target in the same directory
I hope by showing you some of these resources you can guide yourself towards more specific help.

How to integrate python code with C# in Visual Studio 2019

Python code, which is executed on Google Colab and downloaded in .py file how to integrate it with C# code in Visual Studio 2019. On button click, Python code should execute in background and output should be displayed on WPF application.
Python code can be executed in c# by IronPython library and via command prompt. In IronPython I feel some issues. So, I will suggest you to make a process and execute it by cmd. Here is the code to do so.
```Process proc = new Process();
ProcessStartInfo info = new ProcessStartInfo();
info.WindowStyle = ProcessWindowStyle.Normal;
info.FileName = "cmd.exe";
info.Arguments = "/C python code.py \""+arguments+"\"";
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
info.CreateNoWindow = false;
proc.StartInfo = info;
proc.Start();
proc.WaitForExit();
string line = "";
while (!proc.StandardOutput.EndOfStream)
{
line += proc.StandardOutput.ReadLine();
}```
But you have to install all the libraries in PC first which must be overall in the PC not only in some folder.

QProcess will not open python script

I cannot figure out why this does not work:
void Controller::on_buttonVisualTracking_clicked()
{
QProcess *trackingProcess = new QProcess();
trackingProcess->start("python C:\\visualTracking.py");
}
The specific script here is a pychart script, and if I simply run it from the command line, it executes correctly, opening up a window that displays the chart. That is something that I should emphasize, I'm expecting a new window to open displaying the pychart, which is what I get if I run the script myself.
I also tried this code to see if QProcess simply wasn't working. However this worked as expected and an empty notedpad window appeared.
void Controller::on_buttonVisualTracking_clicked()
{
QProcess *trackingProcess = new QProcess();
trackingProcess->start("notepad");
}
So then I thought maybe something is wrong with how I'm supplying arguments, so I tried this, which opened a notepad window with the visualTracking.py text as you would expect.
void Controller::on_buttonVisualTracking_clicked()
{
QProcess *trackingProcess = new QProcess();
trackingProcess->start("notepad C:\\visualTracking.py");
}
Thus, I'm completely at a loss. Why will QProcess not open up the python script?
UPDATE:
Per suggestions I've now tried these two options, neither one worked.
void Controller::on_buttonVisualTracking_clicked()
{
QString run = "C:\\Development\\Anaconda3\\python.exe";
QStringList args;
args << "C:\\visualTracking.py";
QProcess *trackingProcess = new QProcess();
trackingProcess->start(run, args);
}
and
void Controller::on_buttonVisualTracking_clicked()
{
QString commands = "python C:\\visualTracking.py";
QProcess *trackingProcess = new QProcess();
trackingProcess->start("cmd");
trackingProcess->write(commands.toLatin1().data());
if(!trackingProcess->waitForStarted()){};
}
UPDATE:
I thought I had a solution to this, but unfortunately I'm once again, on the development machine, unable to run python scripts again. I've no idea why the behavior changes randomly. My only guess is some windows security setting blocking my app from running a script, but I do not have any evidence to suggest this
With QProcess, you can only start real executables, not scripts. Therefore, you need to run the python interpreter python.exe and give your script as an argument.
See this answer for an example on how to do that. You might need to specify the full path to python.exe to get it to work for you, for example "C:\\Python26\\python.exe".
I see this problem.
But able to resolve by starting cmd first.
Also call ::waitForStarted to block until the process has started.
Check if it works for you (Details in comments).
//YOUR PY COMMAND
QString pyCommand("python C:\\visualTracking.py \n"); //try with out " \n" also...
//CREATE A PROCESS OBJECT
QProcess *qprocess = new QProcess(this);
//START THE CMD
qprocess->start("cmd");
//WRITE YOUR PY COMMAND TO PROCESS
qprocess->write(pyCommand.toLatin1().data());
//BLOCK THE PROCESS UNTILL IT STARTED
if (!qprocess->waitForStarted())
{
}
Are you using Qt5.8.0 MinGW version? I encountered the same issue and after switching to the Qt5.8.0 MSVC version everything worked just fine.
I haven't tried other version yet, but I think this may be the problem. Hope this help
UPDATE
I tried the QT 5.10.0 MinGW version, the bug still exist. However, using the gcc and g++ of manual installed MinGW won't have the same problem. I guess it's because the MinGW version shipped with the Qt is probably too old?
I've had a similar problem with an interactive script; the solution was to force it to run interactively:
auto *process = new QProcess{this};
connect(process, &QProcess::errorOccurred, []{
qFatal("process error occurred");
});
process->start("python", {"-i", "myscript.py"});

calling python script from node.js

I want to call python script from node.js
Here is my script : my.py
def printme( str ):
# print str;
return str;
printme("I'm first call to user defined function!");
printme("Again second call to the same function");
My node script : testpy.js
var PythonShell = require('python-shell');
var pyshell = new PythonShell('my.py');
pyshell.on('message', function(message) {
console.log(message);
});
but getting error
events.js:85
throw er; // Unhandled 'error' event
Error: spawn python ENOENT
at exports._errnoException (util.js:746:11)
at Process.ChildProcess._handle.onexit (child_process.js:1046:32)
at child_process.js:1137:20
at process._tickCallback (node.js:355:11)
at Function.Module.runMain (module.js:503:11)
at startup (node.js:129:16)
at node.js:814:3
P.S I have install Python shell
Also if I want to execute individual function from node.js to python script. can I do that ?Help
You can simply write the 'my.py' file like this-
def printme(str):
return str;
print(printme("I'm first call to user defined function!"));
Check if the path given is correct and check for indentation errors.
Your print statement (my.py line 2) is commented out so nothing will be output and the message event will therefore never fire. Uncomment your print statement, the Node PythonShell object will redirect the stdout (which print writes to) and fire a message event with the output.
As for your error, it looks like the python script isn't being found in the current directory. See https://docs.python.org/2/library/errno.html for error codes and what they mean. Make sure your script is in the right directory or set your python shell to the correct directory using os.chdir.
I think that you need to set up the python script to take in standard input like this
import sys
for v in sys.argv[1:]:
print v
Also when setting up the code the way you have it you need to do a PyhtonShell.send('message'), but I would need to see more of your code because I don't see how you are sending data to the python shell through Node.js.
You can simply import Npm Pythonshell using let keyword instead of const Keyword.
let {PythonShell} = require('python-shell')
this works for me

Categories