Subprocess.popen() 无法在 Windows 上的参数内使用引号

Som*_*ter 5 python windows subprocess call popen

我在 SO 上浏览了一篇又一篇文章,寻找一种使用 subprocess.popen 在参数内使用引号的方法,但我似乎找不到方法。

这在命令行下工作得很好

runme.bat --include="check|check2"
Run Code Online (Sandbox Code Playgroud)

Python

#!/usr/bin/python
import sys
import subprocess
import shlex

#command_line = "./runme.sh --include=\"check|check2\""
command_line = "runme.bat --include=\"check|check2\""

arg = shlex.shlex(command_line)
arg.quotes = '"'
arg.whitespace_split = True
arg.commenters = ''
command_line_args = list(arg)
print command_line_args

command_line_process = subprocess.Popen(
    command_line_args,
    universal_newlines=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
)

line = ""
while True:
    line = command_line_process.stdout.readline()
    if line:
        print line
        break
Run Code Online (Sandbox Code Playgroud)

运行文件

echo %* >> someargs.txt
Run Code Online (Sandbox Code Playgroud)

runme.sh

#!/bin/bash
echo $@
Run Code Online (Sandbox Code Playgroud)

我听说 subprocess.call() 是解决这个问题的方法,但我希望能够在程序运行时逐行迭代子进程的输出。

编辑:

这似乎是Python中的一个错误,因为在cmd中运行runme.bat可以正常工作,在linux中运行runme.py可以正常工作,只有在Windows上运行runme.py时才能正常工作。我在这里创建了一张票。

编辑2:

这显然不是一个 python bug 哈哈。查看所选答案。

jfs*_*jfs 4

在 Windows 上,字符串是本机 API。为了避免不必要的转换,请将命令作为字符串传递:

#!/usr/bin/env python
from __future__ import print_function
import subprocess

command = 'runme.bat --include="check|check2"'
process = subprocess.Popen(command,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
    universal_newlines=True, bufsize=1)
for line in iter(process.stdout.readline, ''):
    print(line, end='')
Run Code Online (Sandbox Code Playgroud)

stderr=subprocess.STDOUT将 stderr 合并到 stdout。如果您设置了stderr=PIPE,那么您应该与读取process.stderr并行process.stdout否则您的程序可能会死锁。

Popen()将字符串传递给CreateProcess()Windows 函数。如果子进程实际上是一个批处理文件;您可能应该shell=True显式传递以明确该命令是使用cmd.exe规则解释的(^|等是元字符,有关更多详细信息,请阅读此答案中的链接)。

%1如果您想使用而不是传递参数,%*以便它包含
整个--include="check|check2"(不仅仅是--include),那么您可以在参数周围使用额外的引号,如@eryksun 在评论中建议的那样:

command = '"runme.bat" "--include="check^^^|check2""'
Run Code Online (Sandbox Code Playgroud)

注意:三重^逃离|这里。