How to call python script from c++ (Clion) - python

OK, so after searching a little too hard over the internet I still have my same issue. I have a very simple python script that opens up the specified excel file and then runs a macro.
I know for a fact that my python script runs as it should stand alone.
I know for a fact that my C++ code runs as it should.
But the combo of both creates a 'com_error'. Just so anyone who sees this knows, these are all the tests I have ran:
(1) simple python script (just prints hello) --> passed
(2) use C++ to run same simple .py script --> passed
(3) more advanecd python script (opens excel, runs macro, save and close) --> pass
(4) usc C++ code to run advanced .py script --> fail.
And there is my problem. this has something to do with the win32com.client and an error the server throws because it cant find the file location (but trust me it can because it passed the 'find file' test)
I'm running Windows7, Python 2.7, And the latest version of JetBrains Clion (2017.1.2).
Any help would be so appreciated. Thanks! Happy coding.
C++ code:
#include <iostream>
#include <Windows.h>
using namespace std;
int main() {
const char *cmd = "python C:\\Users\\Alex.Valente\\Desktop\\python.py";
PROCESS_INFORMATION processInformation = {0};
STARTUPINFO startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
BOOL result = CreateProcess(NULL, (LPSTR)cmd,
NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS,
GetEnvironmentStrings(), NULL, &startupInfo, &processInformation);
if(!result){
return -1;
}
WaitForSingleObject( processInformation.hProcess, INFINITE );
return 0;
}
Python Script:
from __future__ import print_function
import unittest
import os.path
import win32com.client
import os
class ExcelMacro(unittest.TestCase):
def test_excel_macro(self):
xlApp = win32com.client.DispatchEx('Excel.Application')
xlsPath = r'C:\Users\Alex.Valente\Desktop\Data.csv'
xlApp.Visible = True
wb = xlApp.Workbooks.Open(Filename=xlsPath)
xlApp.Run("PERSONAL.XLSB!PythonTest")
wb.Save()
wb.Close()
xlApp.Quit()
print("Macro ran successfully!")
if __name__ == "__main__":
unittest.main()
And the Error that is printed after I run it:
======================================================================
ERROR: test_excel_macro (__main__.ExcelMacro)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\Alex.Valente\Desktop\python.py", line 25, in test_excel_macro
wb = xlApp.Workbooks.Open(Filename=xlsPath)
File "<COMObject <unknown>>", line 8, in Open
com_error: (-2147417851, 'The server threw an exception.', None, None)
----------------------------------------------------------------------
Ran 1 test in 6.305s
FAILED (errors=1)

Related

Trying to run AutoIt file from Python

I am trying to execute an AutoIt script via Python using os.system(). However, the program freezes and crashes without any error code. When I am executing the AutoIt script manually it works fine.
Python code:
def main():
Exe_file_dir = "C:\\Users\\matan\\Downloads\\npp.8.2.Installer.x64.exe"
os.system("C:\\Users\\matan\\Desktop\\14th\\gal\\The_project\\startAutoIt\\RealMain.exe
" + "Record#"+Exe_file_dir)
Autoit code:
#RequireAdmin
#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <GuiButton.au3>
#include ".\RecordMain.au3"
#include ".\RunMain.au3"
#include <MsgBoxConstants.au3>
Main()
Func Main()
If $CmdLine[0] > 0 Then
If $CmdLine[1] <> #ScriptName Then
$mode = $CmdLine[1]
;~ $dir = $CmdLine[2] ;Now, you can use the variable $PAR in your script.
$parmeters = StringSplit($mode,'#')
$mode = $parmeters[1]
$dir = $parmeters[2]
Endif
Endif
If $mode = 'Record' Then ;RecordMode
RecordMain($dir)
ElseIf $mode = 'Run' Then ;RunMode
RunMain($dir)
EndIf
;~ Global $aFileList[0] ;Reset file list
EndFunc
This the Autoit function I run:
Func RecordMain($sFile) ; Open the installation, and get controls that user click on them until the instalatin ended.
Opt("MouseCoordMode", 2) ; Change relative Coords of Mouse to the active window
_MouseSetOnEvent($MOUSE_WHEELSCROLLDOWN_EVENT, "MouseWheel_Events") ; MouseWheelEvents start
_MouseSetOnEvent($MOUSE_WHEELSCROLLUP_EVENT, "MouseWheel_Events") ; MouseWheelEvents start
If (Not StringInStr($sFile, ".msi") = 0 Or Not StringInStr($sFile, ".MSI") = 0) Then;if it msi fie
$iPID = Run("msiexec /i "&$sFile)
$sLog = StringReplace($sFile, ".msi", ".txt") ; Name for log file.
Else ;if it exe file
$iPID = Run($sFile)
$sLog = StringReplace($sFile, "exe", "txt") ; Name for log file.
EndIf
_FileCreate($sLog) ; Create log file. locate in the wizard location
Global $hFileOpen = FileOpen($sLog, $FO_APPEND) ; Open log file
Global $hDLL = DllOpen("user32.dll") ; For _IsPressed func
While 1
If _IsPressed("01", $hDLL) Then ; When mouse click
$sWinIdentify = WinIdentify() ; Identify the window
$sReturn = GetControlOnMouse(WinGetHandle("[ACTIVE]")) ; Get Control On Mouse
;~ MsgBox($MB_SYSTEMMODAL, "Title", $sReturn, 10)
If Not $sReturn = False Then ; When have control
FileWrite($hFileOpen, $sWinIdentify & $sReturn & #CRLF) ; Write data to file
EndIf
While _IsPressed("01", $hDLL)
Sleep(100)
;~ MsgBox($MB_SYSTEMMODAL, "Title", "sleep", 10)
WEnd
EndIf
If Not ProcessExists($iPID) Then ;check if the file stil open
;~ MsgBox($MB_SYSTEMMODAL, "Title", "before", 10)
ExitLoop
EndIf
WEnd
DllClose($hDLL)
FileClose($hFileOpen) ; Close log file
_MouseSetOnEvent($MOUSE_WHEELSCROLLDOWN_EVENT) ; MouseWheelEvents stop
_MouseSetOnEvent($MOUSE_WHEELSCROLLUP_EVENT) ; MouseWheelEvents stop
EndFunc
I tried to reproduce your issue and copied your Python code and create stub functions for AutoIt functions (see code snippets and possible solution below).
First of all, current version of main() Python function has syntax error (the quotation mark should be on the first line in call os.system(). I didn't manage to edit description). Check your local code (use double backslashes as editor suggested you.). But this is not a cause of issue because you would have seen the error "SyntaxError: EOL while scanning string literal" in terminal
As you said, manually running AutoIt script works fine and you don't see any error in terminal. So I guess that cause in executing of RealMain.exe file. Some antivirus apps block execution of such executable files that operates with important files and folders (user Downloads folder in your case). For example when I tested your code my Windows Security app suggested me to send them this compiled .exe (by Aut2exe.exe utility) and check it. You could miss a blocking notification from your antivirus.
Try to substitute your .exe file to not compiled .au3 file and check result. i.e.
os.system("D:\\tmp\\tmp_autoit\\RealMain.au3 "
+ "Record#"+Exe_file_dir)
But don't forget that default shell behaviour for .au3 files must be 'Run', not 'Edit'. You can check it in advance by double clicking on RealMain.au3 file. But watch for antivirus notification, because AutoIt3.exe also can be blocked.
Also check carefully how and where you run your Python script (adding if __name__ == "__main__": block at the end of script is a good practice).
My code snippets to quick reproduce:
# run_real_main_script.py
import os
def main():
Exe_file_dir = "D:\\tmp\\tmp_autoit\\Sample.log"
os.system("C:\\Users\\myuser\\Downloads\\RealMain.exe "
+ "Record#"+Exe_file_dir)
if __name__ == "__main__":
main()
;~ RunMain.au3
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>
Func RunMain($sFile)
MsgBox($MB_SYSTEMMODAL, "", "Run RunMain() function" & #CRLF & "$sFile=" & $sFile)
EndFunc
;~ RecordMain.au3
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>
Func RecordMain($sFile)
MsgBox($MB_SYSTEMMODAL, "", "Run RecordMain() function" & #CRLF & "$sFile=" & $sFile)
EndFunc
RealMain.au3 is the exact copy of "Autoit code:" snippet in the description.
I executed run_real_main_script.py script with installed Python 3.9.2 interpreter in PowerShell as:
python "D:\tmp\tmp_autoit\check_scripts\run_real_main_script.py"

Run Python app (script on PATH) from Java

I'm facing quite simple problem, yet still not able to figure out what in particular causes that, and - more importantly - how to solve it.
I'm currently on Linux, and I would like to run an python app (script) from a Java application. The script is on PATH, thus I really would like to utilise that (avoid using absolute path to the script), if possible.
However, all I tried resulted in various forms of "File does not exist".
Sample
As a demonstration, I've tried to run one python3-based app (meld)
and one binary-built app (ls) for comparison:
$ which ls
/usr/bin/ls
$ file /usr/bin/ls
/usr/bin/ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=[...], for GNU/Linux 3.2.0, stripped
$ which meld
/usr/bin/meld
$ file /usr/bin/meld
/usr/bin/meld: Python script, UTF-8 Unicode text executable
$ head -n1 /usr/bin/meld
#!/usr/bin/python3
Nextly, I've created simple Java main, which tries several ways how to start theese:
package cz.martlin.processes;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.List;
import java.util.stream.Collectors;
public class ProcessPlaying {
public static void main(String[] args) {
List<List<String>> commands = List.of(
List.of("ls"),
List.of("/usr/bin/ls"),
List.of("meld"),
List.of("/usr/bin/meld"),
List.of("python3", "/usr/bin/meld"),
List.of("/usr/bin/python3", "/usr/bin/meld"),
List.of("sh", "-c", "meld"),
List.of("sh", "-c", "/usr/bin/meld"),
List.of("sh", "-c", "python3 /usr/bin/meld")
);
for (List<String> command : commands) {
run(command);
}
}
private static void run(List<String> command) {
System.out.println("Running: " + command);
//String executable = command.get(0);
//boolean exists = new File(executable).exists();
//System.out.println("Exists the " + executable + " ? " + exists);
try {
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectError(Redirect.INHERIT);
Process proc = pb.start();
// Process proc = Runtime.getRuntime().exec(command.stream().collect(Collectors.joining(" ")));
int code = proc.waitFor();
System.out.println("OK, return code: " + code);
} catch (IOException e) {
System.out.println("Failed to start: " + e.toString());
} catch (InterruptedException e) {
System.out.println("Failed to await: " + e.toString());
}
System.out.println();
}
}
Here are the results:
Running: [ls]
OK, return code: 0
Running: [/usr/bin/ls]
OK, return code: 0
Running: [meld]
Failed to start: java.io.IOException: Cannot run program "meld": error=2, Directory or file doesn't exist
Running: [/usr/bin/meld]
Failed to start: java.io.IOException: Cannot run program "/usr/bin/meld": error=2, Directory or file doesn't exist
Running: [python3, /usr/bin/meld]
python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
Running: [/usr/bin/python3, /usr/bin/meld]
/usr/bin/python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
Running: [sh, -c, meld]
sh: line 1: meld: command not found
OK, return code: 127
Running: [sh, -c, /usr/bin/meld]
sh: line 1: /usr/bin/meld: Directory or file doesn't exist
OK, return code: 127
Running: [sh, -c, python3 /usr/bin/meld]
python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
To sum it up:
all of the commands tried works when executed directly from the shell (either sh or bash)
executing the binary works either by the full path (/usr/bin/ls) or by just the name (ls)
executing the python script the same way doesn't work neither way
when trying to run the python3 interpreter and populate the script path as an argument to the python, now the python yields the script file doesn't exist
trying to populate it as a command to the brand new shell didn't help either
I've tried to use the Runtime#exec (based on this comment: https://stackoverflow.com/a/36783743/3797793) to start the process (both the exec(String) and exec(String[] forms), but no sucess (none of the listed commands did actually execute).
Thus, my question is/are:
What do I understand wrong?
How to start the Python script from Java?
Would some small (ba)sh script wrapper do the job?
Since it's python3-based, Jython wouldn't help here (because the latest one is 2.7.*), would it?
Further requirements:
As mentioned, I would like to be able to avoid using full path to the Python script
Also, I would like to have platform independant solution (at least Linux and Windows compatible)
Thanks in advance

call python script in java application (Error in python import)

I call my python script with java and also pass variables. My The script alone in a PyCharm project works so far, only if I call it via Java (InteliJ) nothing happens.
The program should pass values ​​to my script via Java so that the script changes and saves values ​​in a Word Document (docx).
If I use the version of my script in the Intelij folder, it has problems importing docx.
I think the problem is that in the PyCharm project the docx data is directly in the project. This is not the case with Intelij and it should access the system data from docx.
I have already completely reinstalled lxml and docx but to no avail.
How do I have to change my program structure or my script so that it works.
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class runPython {
public static void main(String[] args) throws IOException {
try {
ProcessBuilder builder = new ProcessBuilder("python", "C://Users//Notebook//IdeaProjects//bhTool_bridge//scripts//main.py", "Annemarie Brekow");
Process process = builder.start();
}
catch (Exception e){
e.printStackTrace();
}
}
}
Python:
from docx import Document
import sys
import os
document = Document('C:/Users/Notebook/IdeaProjects/bhTool_bridge/template/Muster_Rechnung.docx')
workingdirectory=os.getcwd()
def find_replace(paragraph_keyword, draft_keyword, paragraph):
if paragraph_keyword in paragraph.text:
# print("found")
paragraph.text = paragraph.text.replace(paragraph_keyword, draft_keyword)
for paragraph in document.paragraphs:
find_replace("$Kunden-Name", "Annemarie Brekow", paragraph)
print(paragraph.text)
document.save("C:/Users/Notebook/IdeaProjects/bhTool_bridge/template/Muster_Rechnung.docx")
EDIT:
Errormsg
Traceback (most recent call last):
File "C:\Users\Notebook\IdeaProjects\bhTool_bridge\scripts\main.py", line 2, in
from docx import Document
ModuleNotFoundError: No module named 'docx'

Laravel - Python script execution

I have to execute a Python script which pulls a large amount of data to the database. It is working fine while I am running a project using the command php artisan serve, but it is throwing an error after calling the public folder URL given below
localhost/project/public
Error:
The command "python /opt/lampp/htdocs/laravel/projectname/beta/projectname/public/python/pubmed_abstract/pubmed_engine.py '{"term":"cancer"}'" failed.
Exit Code: 1(General error) Working directory: /opt/lampp/htdocs/laravel/infocytosis/beta/infocytosis/public Output:
================ Error Output: ================
Traceback (most recent call last): File "/opt/lampp/htdocs/laravel/projectname/beta/projectname/public/python/pubmed_abstract/pubmed_engine.py", line 5, in from Bio import Entrez ImportError: No module named Bio
Code I used:
$python_path=public_path().'/python/doom_abstract/doom_engine.py';
$variables='{"term":"'.addslashes($request->term).'"}';
$process = new Process("python $python_path '$variables'");
$process->run();
return redirect()->back()->withMessage('Filter saved successfully');
You can try following one
$python_path=public_path('python/doom_abstract/doom_engine.py');
Instead of:
$process = new Process("python $python_path '$variables'");
$process->run();
how about
shell_exec("python $python_path '$variables'")

Call a python method from C/C++, and fail in access violation exception

We wanna call a c/c++ extension in python, and in the extension we need to callback one function in the python script.
Here is the python code
# -*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import ctypes
class MyClass:
def func(self):
print "func"
open("out.txt","w").write("func")
print "func2"
return
mDll = ctypes.CDLL("xx.dll", ctypes.RTLD_GLOBAL)
c = MyClass()
# c.func() is what we wanna run below
mDll.callFunc.argtypes = [ctypes.py_object]
mDll.callFunc(c)
Below is the c source for xx.dll, built by VS 2008:
__declspec(dllexport) int callFunc(PyObject* self){
printf("callFunc\n");
//PyObject* ret = PyObject_CallMethod(self, "func", NULL);
PyObject* ret2 = PyObject_CallFunctionObjArgs(PyObject_GetAttrString(self, (char*)"func") , self, NULL);
printf("callFunc2\n");
return 0;
}
We have tried two methods (PyObject_CallFunctionObjArgs / PyObject_CallMethod),and neither of the two methods failed in the calling. The results shows:
Traceback (most recent call last):
File "test\tCall.py", line 19, in <module>
mDll.callFunc(c)
WindowsError: exception: access violation writing 0x0000000C
How could we call the MyClass.func ?
ctypes releases the GIL before calling anything loaded with CDLL. You need to explicitly hold it, or use ctypes.PyDLL, or actually, it's probably best to just write a normal extension module instead of loading DLLs manually.
Also, manage your references, and don't pass self to the func method; that happens implicitly.
(I don't know if those are all of the problems, but those are the ones I noticed.)

Categories