Does Python's subprocess.Popen accept spaces in paths?
Question:
I have a simple Python script:
log("Running command: " + str(cmd))
process = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, close_fds=close_fds)
I’m executing it on Windows on the same python version 2.6.1, but on different VMs. One is Windows Server 2008 Enterprise, the second one it Windows Server Enterprise and I got error on only one of them.
The log from Windows Server Enterprise:
Running command: C:Program FileMyProgramprogram.exe "parameters"
Error: 'C:\Program' is not recognized as an internal or external command
The log from Windows Server 2008 Enterprise:
Running command: C:Program FileMyProgramprogram.exe "parameters"
...
The error happens only for one environment. I know that the path should be escaped, but how is that possible that the subprocess.Popen
could handle the path with space and without escaping?
Answers:
Paths with spaces need to be escaped. The easiest way to do this is to setup the command as a list, add shell=True and let python do the escaping for you:
import subprocess
cmd = [r"C:Program FileMyProgramprogram.exe", "param1", "param2"]
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE,stdin=subprocess.PIPE, close_fds=close_fds)
Consider this:
command = "C:Path argumentorpath"
How do you differentiate between an executable C:Path
with an argument argumentorpath
and a command path
located at C:Path argumentor
? If you pass an list instead of a string to Popen
however, the intent is unambiguous:
command = ["C:Path argumentorpath"]
proc = Popen(command, ...)
For anybody that stumbles upon this post looking for a solution to this, encapsulating the executable in quotes works on Windows and replacing ‘ ‘ with ‘ ‘ works in bash (Linux/MacOS) for Popen shell commands.
Here’s what worked for me:
from subprocess import Popen
cmd = '/path/to/some executable with spaces'
# Execute in Windows shell:
Popen(r'"{}"'.format(cmd), shell=True)
# Execute in bash shell:
Popen(cmd.replace(' ', ' '), shell=True)
Here is what I found to work for windows :
Either of the below statements will open the specified file with the program specified :
subprocess.run('start EXCEL.exe "%s"' %cmd_path, shell=True)
os.system('start EXCEL.exe "%s"' %cmd_path)
Unfortunately, subprocess.run does not work with the iterable arguments. The following for me did not work :
subprocess.call(['start','EXCEL.EXE', f'"%s"'%save_path])
subprocess.run(['start','EXCEL.EXE', f"%s"%save_path])
os.system('start EXCEL.EXE ' + f"%s"%save_path)
An ugly work around, but a very effective one nevertheless
– Use python to create a batch file with your command
– Execute the batch file
– Delete the batch file
def runThis(command):
tempBatch = open(r'c:tempTemporaryBatchFile.bat', 'w')
tempBatch.write(command)
tempBatch.close()
subprocess.call(r'c:tempTemporaryBatchFile.bat')
And then use something like this:
runThis('start "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" "' + Directory + '\' + FileName + '"')
I have a simple Python script:
log("Running command: " + str(cmd))
process = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, close_fds=close_fds)
I’m executing it on Windows on the same python version 2.6.1, but on different VMs. One is Windows Server 2008 Enterprise, the second one it Windows Server Enterprise and I got error on only one of them.
The log from Windows Server Enterprise:
Running command: C:Program FileMyProgramprogram.exe "parameters"
Error: 'C:\Program' is not recognized as an internal or external command
The log from Windows Server 2008 Enterprise:
Running command: C:Program FileMyProgramprogram.exe "parameters"
...
The error happens only for one environment. I know that the path should be escaped, but how is that possible that the subprocess.Popen
could handle the path with space and without escaping?
Paths with spaces need to be escaped. The easiest way to do this is to setup the command as a list, add shell=True and let python do the escaping for you:
import subprocess
cmd = [r"C:Program FileMyProgramprogram.exe", "param1", "param2"]
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE,stdin=subprocess.PIPE, close_fds=close_fds)
Consider this:
command = "C:Path argumentorpath"
How do you differentiate between an executable C:Path
with an argument argumentorpath
and a command path
located at C:Path argumentor
? If you pass an list instead of a string to Popen
however, the intent is unambiguous:
command = ["C:Path argumentorpath"]
proc = Popen(command, ...)
For anybody that stumbles upon this post looking for a solution to this, encapsulating the executable in quotes works on Windows and replacing ‘ ‘ with ‘ ‘ works in bash (Linux/MacOS) for Popen shell commands.
Here’s what worked for me:
from subprocess import Popen
cmd = '/path/to/some executable with spaces'
# Execute in Windows shell:
Popen(r'"{}"'.format(cmd), shell=True)
# Execute in bash shell:
Popen(cmd.replace(' ', ' '), shell=True)
Here is what I found to work for windows :
Either of the below statements will open the specified file with the program specified :
subprocess.run('start EXCEL.exe "%s"' %cmd_path, shell=True)
os.system('start EXCEL.exe "%s"' %cmd_path)
Unfortunately, subprocess.run does not work with the iterable arguments. The following for me did not work :
subprocess.call(['start','EXCEL.EXE', f'"%s"'%save_path])
subprocess.run(['start','EXCEL.EXE', f"%s"%save_path])
os.system('start EXCEL.EXE ' + f"%s"%save_path)
An ugly work around, but a very effective one nevertheless
– Use python to create a batch file with your command
– Execute the batch file
– Delete the batch file
def runThis(command):
tempBatch = open(r'c:tempTemporaryBatchFile.bat', 'w')
tempBatch.write(command)
tempBatch.close()
subprocess.call(r'c:tempTemporaryBatchFile.bat')
And then use something like this:
runThis('start "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" "' + Directory + '\' + FileName + '"')