On Windows, why does os.system recognise space in a path when a filename exists but not when a file doesn’t exist?
Note that I know it’s recommended to use subprocess, and I am somewhat familiar with subprocess.run and subprocess.Popen but i’m asking here about os.system
I understand that os.system calls something similar to CMD in that the error message is the same or largely the same.
I will use wordpad.exe as an example because it’s on Windows systems by default, so is easy to test.
wordpad.exe does exist. zordpad.exe doesn’t exist.
import os
os.system(R'"C:\Program Files\Windows NT\Accessories\wordpad.exe"')
os.system(R'"C:\Program Files\Windows NT\Accessories\zordpad.exe"')
I’m using R there to make it a raw string so that the backslash is fine for whatever path. (though I could remove the R and put \ there).
And i’m using single quotes around the double quotes, so as to make the single quotes literal, so that when cmd gets called, it will see the double quotes as special and then preserve the spaces.
The first line in that python code works, it opens wordpad.exe fine.
The second line in that python code, trying to open "zordpad.exe" (a file that doesn’t exist), gives an error
C:\blah>python issuewithos_dot_system4.py
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
C:\blah>
So it breaks on the space, but only when the file doesn’t exist!!!
CMD doesn’t have that problem
C:\blah>"C:\Program Files\Windows NT\Accessories\zordpad.exe"
'"C:\Program Files\Windows NT\Accessories\zordpad.exe"' is not recognized as an internal or external command, operable program or batch file.
C:\blah>
I could escape the space with the cmd escape character.. The escape character by cmd is ^
And so the following line works
os.system(R"C:\Program^ Files\Windows^ NT\Accessories\zordpad.exe")
(and I rightly don’t use single quotes around the double quoted string above, I don’t want to have single quotes around the double quotes there, otherwise i’d be making the double quotes literal which goes to cmd(or "cmd") as special and on cmd would make the caret literal, and would be a funny file path).
So back to the question..
Why is it that this os.system(R'"C:\Program Files\Windows NT\Accessories\wordpad.exe"') works
(imply that that syntax ensures spaces are preserved)
But this os.system(R'"C:\Program Files\Windows NT\Accessories\zordpad.exe"') (trying to call an executable that doesn’t exist), gives not just an error message (an error message would be expected). But it gives a broken error message, and the broken error message it gives logically implies that spaces weren’t preserved. (so it thinks C:\Program is the name of the executable, perhaps being passed an argument of "Files\...")
How do you explain that behaviour with the broken error message when the file doesn’t exist? It’s not seeing the space as literal but OK so why did it manage to see the space as literal when the filename did exist?!
Added
I spoke to a python expert that thought maybe it used the CreateProcess WinAPI function though found that it used wsystem function https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/system-wsystem?view=msvc-170 https://github.com/python/cpython/blob/main/Modules/posixmodule.c#L4893 though the mystery of the broken error message remains.
>Solution :
That’s simply because os.system is effectively system(), which runs commands as cmd /C command. Putting this exact setup into a cmd.exe:
C:\Users\User>cmd /C "C:\Program Files\Windows NT\Accessories\wordpad.exe"
C:\Users\User>cmd /C "C:\Program Files\Windows NT\Accessories\zordpad.exe"
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
The message is derived as is from directly via system() calling cmd /C, and not a fault in Python.