当多个参数包含空格时如何使用子进程?

21 python subprocess

我正在开发一个包装脚本,它将运行vmware可执行文件,允许虚拟机启动/关闭/注册/注销操作的自动化.我正在尝试使用子进程来处理调用可执行文件,但子进程无法正确处理可执行文件路径和可执行文件参数中的空格.下面是一段代码片段:

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
Run Code Online (Sandbox Code Playgroud)

如果我调用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
Run Code Online (Sandbox Code Playgroud)

如果我调用vm_start函数,它需要一个path-to-vm参数,我得到以下输出:

$ ./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.
Run Code Online (Sandbox Code Playgroud)

显然,嵌入空格的第二个参数的存在正在改变子进程解释第一个参数的方式.有关如何解决此问题的任何建议?

python2.5.2/cygwin的/ WINXP

nos*_*klo 5

'c:\Program' is not recognized as an internal or external command,
operable program or batch file.
Run Code Online (Sandbox Code Playgroud)

要获得此消息,您要么:

  1. 使用shell=True:

    vmrun_cmd = r"c:\Program Files\VMware\VMware Server\vmware-cmd.bat"
    subprocess.Popen(vmrun_cmd, shell=True)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在代码的其他部分更改vmrun_cmd

  3. 从vmware-cmd.bat中的某些内容中获取此错误

要尝试的事情:

如果可行,那么引用问题是不可能的.如果没有,你就已经解决了这个问题.


dar*_*rch 5

我相信 list2cmdline() 正在处理列表参数,它会在空格上分割任何字符串参数,除非字符串包含双引号。所以我期望

vmrun_cmd = r'"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"'
Run Code Online (Sandbox Code Playgroud)

成为你想要的样子。

您可能还希望将其他参数(例如target_vm)用双引号引起来,假设它们也各自代表要呈现给命令行的不同参数。就像是

r'"%s"' % target_vm
Run Code Online (Sandbox Code Playgroud)

(例如)应该适合。

请参阅list2cmdline 文档


Tof*_*eth 5

如果路径中有空格,我发现最简单的解释方法就是这样.

subprocess.call('""' + path + '""')
Run Code Online (Sandbox Code Playgroud)

我不知道为什么它需要双倍双引号,但这是有效的.


Jus*_*tin -3

你为什么使用 r""?我相信,如果您从开头删除“r”,它将被视为可能包含空格的标准字符串。然后,Python 在将字符串发送到 shell 时应正确引用该字符串。

  • 使用 r"...\..." 作为 Windows 文件名是有意义的。 (2认同)