如何在多个参数包含空格时使用subprocess?

24 投票
10 回答
41589 浏览
提问于 2025-04-15 11:19

我正在写一个脚本,这个脚本可以控制vmware的程序,帮助自动化虚拟机的启动、关闭、注册和注销操作。我想用subprocess这个工具来调用这个程序,但发现程序路径和参数中的空格没有被正确处理。下面是一些代码片段:

vmrun_cmd = r"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"
def vm_start(target_vm):
    list_arg = "start"
    list_arg2 = "hard"
    if vm_list(target_vm):
            p = Popen([vmrun_cmd, target_vm, list_arg, list_arg2],   stdout=PIPE).communicate()[0]
            print p
    else:
            vm_register(target_vm)
            vm_start(target_vm)
def vm_list2(target_vm):
    list_arg = "-l"
    p = Popen([vmrun_cmd, list_arg], stdout=PIPE).communicate()[0]
    for line in p.split('\n'):
            print line

当我调用vm_list2这个函数时,得到的输出是:

$ ./vmware_control.py --list                                                
C:\Virtual Machines\QAW2K3Server\Windows Server 2003 Standard Edition.vmx
C:\Virtual Machines\ubunturouter\Ubuntu.vmx
C:\Virtual Machines\vacc\vacc.vmx
C:\Virtual Machines\EdgeAS-4.4.x\Other Linux 2.4.x kernel.vmx
C:\Virtual Machines\UbuntuServer1\Ubuntu.vmx
C:\Virtual Machines\Other Linux 2.4.x kernel\Other Linux 2.4.x kernel.vmx
C:\Virtual Machines\QAClient\Windows XP Professional.vmx

当我调用vm_start这个函数时,它需要一个虚拟机路径的参数,结果输出是:

$ ./vmware_control.py --start "C:\Virtual Machines\ubunturouter\Ubuntu.vmx"
'c:\Program' is not recognized as an internal or external command,
operable program or batch file.

看起来,第二个参数中有空格的存在,影响了subprocess对第一个参数的理解。有没有什么建议可以解决这个问题呢?

python2.5.2/cygwin/winxp

10 个回答

4

‘c:\Program’ 这个路径没有被识别为内部或外部命令,也不是可操作的程序或批处理文件。

出现这个提示的原因可能有:

  1. 你在使用 shell=True

    vmrun_cmd = r"c:\Program Files\VMware\VMware Server\vmware-cmd.bat"
    subprocess.Popen(vmrun_cmd, shell=True)
    
  2. 你在代码的其他地方修改了 vmrun_cmd

  3. 这个错误是从 vmware-cmd.bat 文件里面产生的

可以尝试以下方法:

  • 打开一个 Python 提示符,运行以下命令:

     subprocess.Popen([r"c:\Program Files\VMware\VMware Server\vmware-cmd.bat"])
    

如果这个命令能成功运行,那就说明引号的问题可以排除了。如果不行,那你就找到了问题所在。

5

我认为 list2cmdline() 这个函数在处理你的列表参数时,会根据空格来分割字符串参数,除非这个字符串里面有双引号。所以我预计

vmrun_cmd = r'"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"'

就是你想要的结果。

你可能还想把其他参数(比如 target_vm)用双引号括起来,因为它们也代表了要传给命令行的不同参数。像这样的格式

r'"%s"' % target_vm

(例如)应该就合适了。

你可以查看 list2cmdline 的文档 来了解更多信息。

8

如果你的路径中有空格,我发现最简单的方法是这样处理。

subprocess.call('""' + path + '""')

我也不太清楚为什么需要用两个双引号,但这样做就是有效的。

撰写回答