Python子进程调用在Mac OS X上找不到完整路径

时间:2013-06-16 22:12:28

标签: python macos subprocess

在我的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

如果我把它直接放入终端,那就完美了。

我错过了什么?

1 个答案:

答案 0 :(得分:7)

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

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

    from subprocess import call
    call('/Applications/BitRock InstallBuilder for Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh')
    
  2. 或再次没有shell(显式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. 另一种方法是使用shell并引用:

    from subprocess import call
    call('"/Applications/BitRock InstallBuilder for Qt 8.5.2/bin/Builder.app/Contents/MacOS/installbuilder.sh"',
         shell=True)
    
  5. 我建议尽可能不使用shell(主要是出于安全考虑),请记住,如果您不使用“list”,则必须将参数传递给命令call(['/bin/echo', 'foo', 'bar']) 外壳

    (无壳,有利):

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

    或使用shell

    foo bar\n

    (两个调用具有相同的输出({{1}})