I am creating a code editor, and I am trying to create a run feature. Right now I see that the problems come when I encounter a folder with a space in its name. It works on the command line, but not with os.system().
def run(event):
if open_status_name != False:
directory_split = open_status_name.split("/")
for directory in directory_split:
if directory_split.index(directory) > 2:
true_directory = directory.replace(" ", "\s")
print(true_directory)
data = os.system("cd " + directory.replace(" ", "\s"))
print(data)
I tried to replace the space with the regex character "\s" but that also didn't work.
os.system runs the command in a shell. You'd have to add quotes to get the value though: os.system(f'cd "{directory}"'). But the cd would only be valid for that subshell for the brief time it exists - it would not change the directory of your python program. Use os.chdir(directory) instead.
Note - os.chdir can be risky as any relative paths you have in your code suddenly become invalid once you've done that. It may be better to manage your editor's "current path" on your own.
I was able to open command prompt and change the directory to required location using the subprocess module, but I was unable to pass further arguments to run an application along with some command line arguments. I am new to the subprocess module, so I did some search over stackoverflow couldn't find the desired result.
Mycode:
import subprocess
path = r"C:/Users/Application_Folder"
p = subprocess.Popen(r"cmd.exe", cwd="C:/Project_Files", shell=True)
Desired output:
Path: C:\Users\Application_folder\Application.exe
Need to open the cmd prompt in windows at the Application_folder location,
run the Application.exe by passing some command line arguments, using python
Just pass the command line you actually want to execute, with the executable path and whatever arguments you want to pass:
command_line = [r'C:\Users\Application_Folder\Application.exe', '/argument1', '/argument2']
p = subprocess.Popen(command_line, cwd=r'C:\Project_Files')
A couple of notes to keep in mind:
You shouldn't use shell=True. It's not necessary here -- in fact it's almost never necessary -- but it does introduce a potential security risk.
The whole point of raw string literals (starting with r' or r") is to change how backslash characters within the string are interpreted. r'C:\Program Files' is exactly the same string as "C:\\Program Files". If your string doesn't have backslashes in it, don't bother using the r prefix.
I have a Perl script from which I am calling a Python script.
I am using:
system "python script.py '".$var1."' '".$var2."' '".$var3."' '".$var4."' '".$var5."'";
Where, $var1 = "'Nostoc azollae' 0708", which has single quotes in the string.
In the script.py script, I am using:
var1 = sys.argv[1]
And if I print var1, it only prints: Nostoc and the rest is not printed, rest is working fine.
So, clearly the Python script is not receiving the string with the ' included.
What can be a solution to this?
Avoid shell invocation when using system() by using separate parameters instead of joining them all together,
system("python", "script.py", $var1, $var2, $var3, $var4, $var5);
Trying to call a python script on Vba and I am a newb. I tried converting the main script to an exe using py2exe and then calling it from VBA (shell) but the main script calls other scripts therefore it becomes complicated and I messed it up (my exe is not functional). Besides, the the main script is a large file and I do not want to revise it a lot.
Bottomline, is there a way to call the main script from excel vba, without converting the script to an exe file.
So far, I tried:
RetVal = Shell("C:\python27\python.exe " & "import " & "C:\\" & "MainScriptFile")
It starts python.exe but does nothing else. Then I tried:
RetVal = Shell("C:\Windows\System32\cmd.exe " & "python " & "C:\\Python27\\hello.py")
It starts command prompt but does not even start python.
P.S. I checked all the related questions in the forum, they do not solve my prob.
Try this:
RetVal = Shell("<full path to python.exe> " & "<full path to your python script>")
Or if the python script is in the same folder as the workbook, then you can try :
RetVal = Shell("<full path to python.exe> " & ActiveWorkBook.Path & "\<python script name>")
All details within <> are to be given. <> - indicates changeable fields
I guess this should work. But then again, if your script is going to call other files which are in different folders, it can cause errors unless your script has properly handled it. Hope it helps.
I just came across this old post. Nothing listed above actually worked for me. I tested the script below, and it worked fine on my system. Sharing here, for the benefit of others who come to this spot after me.
Sub RunPython()
Dim objShell As Object
Dim PythonExe, PythonScript As String
Set objShell = VBA.CreateObject("Wscript.Shell")
PythonExe = """C:\your_path\Python\Python38\python.exe"""
PythonScript = "C:\your_path\from_vba.py"
objShell.Run PythonExe & PythonScript
End Sub
There are a couple of ways to solve this problem
Pyinx - a pretty lightweight tool that allows you to call Python from withing the excel process space
http://code.google.com/p/pyinex/
I've used this one a few years ago (back when it was being actively developed) and it worked quite well
If you don't mind paying, this looks pretty good
https://datanitro.com/product.html
I've never used it though
Though if you are already writting in Python, maybe you could drop excel entirely and do everything in pure python? It's a lot easier to maintain one code base (python) rather than 2 (python + whatever excel overlay you have).
If you really have to output your data into excel there are even some pretty good tools for that in Python. If that may work better let me know and I'll get the links.
To those who are stuck wondering why a window flashes and goes away without doing anything the python script is meant to do after calling the shell command from VBA:
In my program
Sub runpython()
Dim Ret_Val
args = """F:\my folder\helloworld.py"""
Ret_Val = Shell("C:\Users\username\AppData\Local\Programs\Python\Python36\python.exe " & " " & args, vbNormalFocus)
If Ret_Val = 0 Then
MsgBox "Couldn't run python script!", vbOKOnly
End If
End Sub
In the line args = """F:\my folder\helloworld.py""", I had to use triple quotes for this to work. If I use just regular quotes like: args = "F:\my folder\helloworld.py" the program would not work. The reason for this is that there is a space in the path (my folder). If there is a space in the path, in VBA, you need to use triple quotes.
This code will works:
your_path= ActiveWorkbook.Path & "\your_python_file.py"
Shell "RunDll32.Exe Url.Dll,FileProtocolHandler " & your_path, vbNormalFocus
ActiveWorkbook.Path return the current directory of the workbook. The shell command open the file through the shell of Windows.
You can also try ExcelPython which allows you to manipulate Python object and call code from VBA.
Try this:
retVal = Shell("python.exe <full path to your python script>", vbNormalFocus)
replace <full path to your python script> with the full path
To those who are stuck wondering why a window flashes and goes away without doing anything, the problem may related to the RELATIVE path in your Python script. e.g. you used ".\". Even the Python script and Excel Workbook is in the same directory, the Current Directory may still be different. If you don't want to modify your code to change it to an absolute path. Just change your current Excel directory before you run the python script by:
ChDir ActiveWorkbook.Path
I'm just giving a example here. If the flash do appear, one of the first issues to check is the Current Working Directory.
ChDir "" was the solution for me. I use vba from WORD to launch a python3 script.
In my case, as I have my script in a different directory than my ms access document and, in that script I import variables from other scripts, I had to change the directory first. Then I can use correctly the shell function.
ChDir "C:\Users\directory_where_the_script_is"
Call Shell("C:\Users\...\python.exe " & "your_script_name.py", 1)
for me this not working
RetVal = Shell(" " & ActiveWorkBook.Path & "<python script name>")
for me this :
RetVal = Shell("python3" & " " & "C:\a\b\c\xyz.py")
I think above answers have a catastrophic problem:
after running the macro,cmd window would close automatically, instantly. In case output is not as expected you would have absolutely zero debug information.
Finally I found a better way in which case, cmd window remains open and shows all the information (print of python) and error log.
code as below:
Sub RunPythonScript()
cwd = ActiveWorkbook.Path 'current working directory
workbookName = ActiveWorkbook.Name
pythonScriptName = "main.py"
workbookNameWithPath = cwd & "\" & workbookName
pythonScriptNameWithPath = cwd & "\" & pythonScriptName
pythonExePath = "C:\Users\USERNAME\AppData\Local\Programs\Python\Python39\python.exe" ' change path as output of "where python"
Shell "cmd.exe /k """"" & pythonExePath & """ """ & pythonScriptNameWithPath & """""", vbNormalFocus
End Sub
I got a program running on my local machine which uses some files. I create the reference to the files by using: os.path.join( tempfile.gettempdir(), 'filename.txt' )
After that I'm running a program which accepts some parameters --log-file filepath where filepath is one of the files I just explained above.
On my machine python creates backslashes for the paths but not double backslashes and the program complains because it's considered an escape character and should be a double backslash.
Is there any standard way of making sure that I get a working path with double backslashes in python? I could use regex but I would prefer something similar to what os. provides. Maybe I'm missing something.
I'm calling the program using subprocess.Popen:
self._proc = subprocess.Popen( command.split( ' ' ) )
where command is something like pcix.exe --log-file file_path
Also, running a test on my console shows that my python does not produce double backslash for paths:
>>> print os.path.join(tempfile.gettempdir(), "test.txt")
c:\users\manilo~1\appdata\local\temp\test.txt
Leaving out the print command produces the same path:
>>> os.path.join(tempfile.gettempdir(), "test.txt")
c:\users\manilo~1\appdata\local\temp\test.txt
Any idea why?
P.S. The platform i'm running is CPython
Try:
print os.path.join(tempfile.gettempdir(), "test.txt").replace('\\\\','\\\\\\\\')