I am attempting to execute a python script from a C++ program. The problem that I am having is that I am unable to execute my python script.
If I take out the lpParameter value by setting it equal to NULL everything works fine, my program launches the python terminal and then my program finishes when I exit the python terminal.
I have a feeling that it has to do with the lpParameters field separating arguments with spaces, so I attempted to the entire python script in escaped quotation marks.
#include "windows.h"
#include "shellapi.h"
#include <iostream>
using namespace std;
int main()
{
cout<<"About to execute the shell command";
SHELLEXECUTEINFO shExecInfo;
shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
shExecInfo.fMask = NULL;
shExecInfo.hwnd = NULL;
shExecInfo.lpVerb = "runas";
shExecInfo.lpFile = "C:\\Python25\\python.exe";
shExecInfo.lpParameters = "\"C:\\Documents and Settings\\John Williamson\\My Documents\\MyPrograms\\PythonScripts\\script.py\"";
shExecInfo.lpDirectory = NULL;
shExecInfo.nShow = SW_NORMAL;
shExecInfo.hInstApp = NULL;
ShellExecuteEx(&shExecInfo);
return 0;
}
What happens when I launch this code is my program runs, quickly pops up another terminal that is quickly gone and then my original terminal says the task is complete. In reality though the python script that I specified is never executed.
Not really an answer, but too long for a comment.
The problem with those kind of execution in a new window, it the as soon as the program has ended the window is closed. As a window has been opened, it is likely from the point of view of the launching program all is fine.
My advice here would be to use a cmd /k that forces a window to keep opened after the end of the program :
shExecInfo.lpFile = "cmd";
shExecInfo.lpParameters = "/k C:\\Python25\\python.exe \"C:\\Documents and Settings\\John Williamson\\My Documents\\MyPrograms\\PythonScripts\\script.py\"";
At least if there is an error anywhere, you will be given a chance to see it.
Turns out the issue was with permissions and setting this parameter:
shExecInfo.lpVerb = "runas";
Instead I left it
shExecInfo.lpVerb = NULL;
and also filled in the directory parameter and it is working now.
Related
I am working on a PHP back that uses python scripts. In PHP, queries and processes are carried out that at the end are passed as arguments to the script, a string is created with the command that is finally executed with exec ()
$arg4Json= str_replace("'", "´", json_encode($arg4));
$command = "python ../path/of/file"
. "/script.py {$arg1} "
. "{$arg2} {$arg3} '{$arg4Json}'";
$output = null;
$returnVal = null;
exec($command, $output, $returnVal);
This was working perfectly. However, in a certain query the arg4Json turns out to be too long and the service crashes. Try to run the command directly in the console with the same arguments and it returns the message:
python: Argument list too long
I have investigated about it and apparently it is a matter related to the maximum length allowed by the console to execute the command and that it is necessary to increase the limits. In the end I was able to increase the 'stack size' and leave it unlimited to test if it worked but it keeps throwing me the same error.
ulimit_list
I would appreciate if someone can guide me on how I can solve this problem. The project runs on a linux server with ubuntu on Apache2.
why not put arguments in a file. and change the behaviour of your program to read arguments from the file instead of passing them as arguments. it's more efficient i think
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've made a bunch of tweaks to NPP following this guide, and so far it's gone over well.
But I have a somewhat annoying problem. I want to use input commands in my code.
If the console is closed, this isn't a problem—it pops up and I can type right away in the input field just fine, no clicking.
But when I edit the code and re-run the script (without closing the console), the console clears and runs the program, but I have to click over to be able to interact.
I don't want to close the NppExec console every time I finish the script.
I don't want to have to click over on the console every time I run the script.
As a bonus, I don't want to have to kill my script every time I run it again, either.
I just want to run, type required inputs, go back to editing, re-run, type, etc. without interruptions, if possible..
Can anyone help me with this?
Thank you....
Please check the NppExec Manual for NppExec ver. 0.6 RC2. It includes a lovely script in the section "4.6.4. Running Python & wxPython":
npp_console - // disable any output to the Console
npp_save // save current file (a .py file is expected)
cd "$(CURRENT_DIRECTORY)" // use the current file's dir
set local #exit_cmd_silent = exit() // allows to exit Python automatically
set local PATH_0 = $(SYS.PATH) // current value of %PATH%
env_set PATH = $(SYS.PATH);C:\Python27 // use Python 2.7
npp_setfocus con // set the focus to the Console
npp_console + // enable output to the Console
python -i -u "$(FILE_NAME)" // run Python's program interactively
npp_console - // disable any output to the Console
env_set PATH = $(PATH_0) // restore the value of %PATH%
npp_console + // enable output to the Console
The command
npp_setfocus con
looks like the one you are looking for.
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"});
I have written a small C program that embeds Python. I'm setting it up correctly using Py_Initialize() and Py_Finalize(), and am able to run scripts either using PyRun_SimpleString or PyRun_SimpleFile. However, I don't know how mimic the behavior of Python's own interpreter when printing variables.
Specifically:
a = (1, 2, 3)
print a
Works fine for me: it prints out (1, 2, 3)
However:
a = (1, 2, 3)
a
Prints out nothing at all. In Python's own interpreter, this would print out (1, 2, 3) as well. How can I make my code do what users would expect and print out the value?
Thanks in advance!
To run the interpreters interactive loop, you should use the function PyRun_InteractiveLoop(). Otherwise, your code will behave as if it were written in a Python script file, not entered interactively.
Edit: Here's the full code of a simple interactive interpreter:
#include <Python.h>
int main()
{
Py_Initialize();
PyRun_InteractiveLoop(stdin, "<stdin>");
Py_Finalize();
}
Edit2: Implementing a full interactive interpreter in a GUI is a bit of a project. Probably the easiest way to get it right is to write a basic terminal emulator connected to a pseudo-terminal device, and use the above code on that device. This will automatically get all subtleties right.
If your aim isn't a full-blown interactive editor, an option might be to use PyRun_String() with Py_single_input as start token. This will allow you to run some Python code as in the interactive interpreter, and if that code happened to be a single expression that doesn't evaluate to None, a representation of its value is printed -- to stdout of course. Here is some example code (without error checking for simplicity):
#include <Python.h>
int main()
{
PyObject *main, *d;
Py_Initialize();
main = PyImport_AddModule("__main__");
d = PyModule_GetDict(main);
PyRun_String("a = (1, 2, 3)", Py_single_input, d, d);
PyRun_String("a", Py_single_input, d, d);
Py_Finalize();
}
This will print (1, 2, 3).
There are still a lot of problems:
No error handling and traceback printing.
No "incremental input" for block commands like in the interactive interpreter. The input needs to be complete.
Output to stdout.
If multiple lines of input are given, nothing is printed.
To really replicate the behaviour of the interactive interpreter is not easy. That's why my initial recommendation was to write a basic terminal emulator in your GUI, which shouldn't be too hard -- or maybe there's even one available.