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.
Related
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!
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.
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.
I am trying to open a py script via VBA Excel.
The script is to interact with engineering software which undertakes finite elements analysis. The script can run directly from the py editor.
They prepared a Python library I have to import at the beginning of the script which also requires some password and log in credentials for the script to interact with that specific software.
I can open simple py scripts (such as the classic Hello World) via the Shell in VBA.
The script that I have prepared is more complex. When opening my script via VBA using the shell it flashes the cmd window and nothing happens.
Below is the subroutine I have coded in VBA to open the Python interpreter and Python script, for illustration: it returns error message 2.
Sub RunPythonScript()
Dim wsh As Object
Dim PythonExe, PythoScript As String
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
Dim errorCode As Long
Dim pth As String
PythonExe = """C:\ProgramData\Bentley\Geotechnical\PLAXIS 2D CONNECT Edition V20\python\python.exe"""
PythoScript = """C:\Users\ukjfv001\Desktop\MyPython\MyAnalysis.py"""
pth = PythonExe & PythoScript
Set wsh = VBA.CreateObject("WScript.Shell")
errorCode = wsh.Run(pth, windowStyle, waitOnReturn)
If errorCode = 0 Then
MsgBox "Done! No error to report."
Else
MsgBox "Program exited with error code " & errorCode & "."
End If
End Sub
There is a lot of information online on how to run Python scripts.
In this forum: How to call python script on excel vba?. I have also created a bat file which I could open via VBA but, got the following error message:
C:\Users\ukjfv001\Desktop\MyPython>"C:\Users\ukjfv001\Anaconda3\python.exe" ""C:\Users\ukjfv001\Desktop\MyPython\MyAnalysis.py""
start
Traceback (most recent call last):
File "C:\Users\ukjfv001\Desktop\MyPython\MyAnalysis.py", line 16, in
from plxscripting.easy import * #call Plaxis scritping library
ModuleNotFoundError: No module named 'plxscripting'
Below is a bit of the Python code which I have to place at the top of the script in the SciTE editor (which comes with the engineering software).
From what I can see in the error message (above) and the bit of code below from plxscripting.easy import there is something I am not doing.
I am new to Python so usually I need practical examples to understand what is to be done.
from plxscripting.easy import * #callS engineering scritping library
inputport = 8888888
plaxispw = some_password
plaxis_path = C:\Users\ukjfv001\... #to here the software is intalled
plaxis_input = Plaxis.exe #software executable
if not process_exists(plaxis_input): #checkS if software is alreayd running
# first launch software
args = [os.path.join(plaxis_path, plaxis_input),"--AppServerPort={}".format(inputport),"--AppServerPassWord={}".format(plaxispw)]
inputprocess = subprocess.Popen(args)
# Initialize new_server with waiting time
s_i, g_i = new_server('localhost', inputport, password=plaxispw, timeout=10.0)
s_i.new()#starts a new Project
#after this point is where I have my Python script...```
I had a similar problem where I got an error running a python script from a scheduler (via running a file) even though it ran in my IDE. I also had to run it from a batch file to see the error, otherwise nothing happened. The issue was that python could not find the path to my custom libraries (which may be your issue, since the error is a library import). I think this can happen if you set your Python Path to custom libraries in your IDE and the environmental variables/ path are not also set (that is what you need to synchronize).
In Spyder, you just go to Tools: Python Path Manager in the menu and hit synchronize. I don't know what IDE you are using, but probably it also has a Python Path Manager if it isn't Spyder.
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"});