Reputation:
In my Python script, this line:
call("/Applications/BitRock\\ InstallBuilder\\ for\\ Qt\\ 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh")
will fail every time with the error OSError: [Errno 2] No such file or directory
However, if I write out the result of that string:
sys.stdout.write("/Applications/BitRock\\ InstallBuilder\\ for\\ Qt\\ 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh")
I get:
/Applications/BitRock\ InstallBuilder\ for\ Qt\ 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh
If I put that directly into the terminal, it works perfect.
What am I missing?
Upvotes: 0
Views: 8723
Reputation: 54111
By default subprocess.call
uses no shell (shell=False
). Therefore, there's no need to escape the spaces. The space escaping is needed in shells (because shells need to know what's the binary's name and what the arguments). Therefore the following uses are all correct (and similar):
Without spawning a shell that spawns the subprocess (favorable):
from subprocess import call
call('/Applications/BitRock InstallBuilder for Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh')
or again without shell (explicit shell=False
and the usage of an argument list)
from subprocess import call
call(['/Applications/BitRock InstallBuilder for Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh'],
shell=False)
But when subprocess
is told to first of all swawn shell which then spawns the subprocess itself, the spaces have to be escaped, because it's a shell command:
from subprocess import call
call('/Applications/BitRock\\ InstallBuilder\\ for\\ Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh',
shell=True)
An alternative would be to use a shell and quotes:
from subprocess import call
call('"/Applications/BitRock InstallBuilder for Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh"',
shell=True)
I'd recommend not to use a shell whenever possible (mostly for security reasons), remember though you have to pass the arguments to the command as a list
if you're not using a shell.
Either (without shell, favourable):
call(['/bin/echo', 'foo', 'bar'])
or with a shell
call('/bin/echo foo bar', shell=True)
(both calls have the same output (foo bar\n
)
Upvotes: 7