0

在我的 Python 脚本中,这一行:

call("/Applications/BitRock\\ InstallBuilder\\ for\\ Qt\\ 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh")

每次都会因错误而失败OSError: [Errno 2] No such file or directory

但是,如果我写出该字符串的结果:

sys.stdout.write("/Applications/BitRock\\ InstallBuilder\\ for\\ Qt\\ 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh")

我得到:

/Applications/BitRock\ InstallBuilder\ for\ Qt\ 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh

如果我将其直接放入终端,则效果很好。

我错过了什么?

4

1 回答 1

7

默认情况下subprocess.call不使用 shell ( shell=False)。因此,没有必要逃避这些空间。shell 中需要空格转义(因为 shell 需要知道二进制文件的名称和参数是什么)。因此,以下用法都是正确的(并且相似):

  1. 不产生产生子进程的外壳(有利):

    from subprocess import call
    call('/Applications/BitRock InstallBuilder for Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh')
    
  2. 或再次没有外壳(显式shell=False和参数列表的使用)

    from subprocess import call
    call(['/Applications/BitRock InstallBuilder for Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh'],
         shell=False)
    
  3. 但是,当subprocess被告知首先生成子进程本身的 swawn shell 时,必须转义空格,因为它是一个 shell 命令:

    from subprocess import call
    call('/Applications/BitRock\\ InstallBuilder\\ for\\ Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh',
         shell=True)
    
  4. 另一种方法是使用外壳和引号:

    from subprocess import call
    call('"/Applications/BitRock InstallBuilder for Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh"',
         shell=True)
    

我建议尽可能不要使用 shell(主要是出于安全原因),但请记住,list如果您不使用 shell,则必须将参数传递给命令。

要么(没有外壳,有利):

call(['/bin/echo', 'foo', 'bar'])

或带壳

call('/bin/echo foo bar', shell=True)

(两个调用具有相同的输出 ( foo bar\n)

于 2013-06-16T22:17:19.997 回答