Subprocess.popen() 不能在 Windows 的参数内使用引号
Subprocess.popen() cannot use quotation marks within arguments on Windows
我在 post 之后通过 post 寻找一种使用 subprocess.popen 在参数内部使用引号的方法,但我似乎找不到方法。
这在命令行中工作正常
runme.bat --include="check|check2"
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
runme.bat
echo %* >> someargs.txt
runme.sh
#!/bin/bash
echo $@
我听说 subprocess.call() 是解决此问题的一种方法,但我希望能够通过子进程的输出逐行迭代 而程序是 运行.
编辑:
这似乎是 Python 中的错误,因为 cmd 中的 运行 runme.bat 可以正常工作, linux 中的 运行 runme.py 可以正常工作正确,只有当 运行 runme.py on Windows 时它才不能正常工作。我创建了一张工单 here。
编辑2:
这显然不是 python 错误,哈哈。查看选择的答案。
另一种获取输出的方法是 subprocess.check_output()
:
import subprocess
command_line = "runme.bat --include=\"check|check2\""
output = subprocess.check_output(
command_line,
shell=True
)
lines = output.splitlines(True)
print lines
要实时查看进程的输出,请参阅:Getting realtime output using subprocess。
编辑: 这是使用 Popen 处理双引号的代码:
from subprocess import Popen, PIPE, STDOUT
command_line = 'ls -la | grep "wheel"'
p = Popen(command_line, stdout=PIPE, stderr=STDOUT, shell=True)
while True:
line = p.stdout.readline()
if not line:
break
else:
print line
您应该不使用shell=True
到运行一个bat
文件。如果必须 运行 某些内置的 shell 命令,则 仅 使用它。换句话说,您所做的使用是无用的,唯一的影响是增加程序的安全漏洞。
此外,请注意 documentation 明确指出,在使用 shell=True
时,建议将命令行作为字符串传递:
If shell is True
, it is recommended to pass args as a string rather
than as a sequence.
所以你应该这样做:
subprocess.check_output('runme.bat --include="check|check2"', shell=True)
如果您只关心输出,则应使用 check_output
函数。这比创建 Popen
对象然后手动读取输出要简单得多。
另请参阅 my answer,了解 shell=True
如何更改参数的含义。
在 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='')
stderr=subprocess.STDOUT
将 stderr 合并到 stdout。如果您设置 stderr=PIPE
那么您应该从 process.stderr
中读取 并行 并从 process.stdout
中读取,否则您的程序可能会死锁。
Popen()
将字符串传递给 CreateProcess()
Windows 函数。如果子进程实际上是一个批处理文件;您可能应该显式传递 shell=True
以明确该命令是使用 cmd.exe
规则解释的(^
、|
等是元字符,有关更多详细信息 ).
如果您想使用 %1
而不是 %*
传递参数,以便它包含
整个 --include="check|check2"
(不仅是 --include
) 然后你可以在参数周围使用额外的引号作为 :
command = '"runme.bat" "--include="check^^^|check2""'
注意:三重 ^
转义 |
这里。
我在 post 之后通过 post 寻找一种使用 subprocess.popen 在参数内部使用引号的方法,但我似乎找不到方法。
这在命令行中工作正常
runme.bat --include="check|check2"
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
runme.bat
echo %* >> someargs.txt
runme.sh
#!/bin/bash
echo $@
我听说 subprocess.call() 是解决此问题的一种方法,但我希望能够通过子进程的输出逐行迭代 而程序是 运行.
编辑:
这似乎是 Python 中的错误,因为 cmd 中的 运行 runme.bat 可以正常工作, linux 中的 运行 runme.py 可以正常工作正确,只有当 运行 runme.py on Windows 时它才不能正常工作。我创建了一张工单 here。
编辑2:
这显然不是 python 错误,哈哈。查看选择的答案。
另一种获取输出的方法是 subprocess.check_output()
:
import subprocess
command_line = "runme.bat --include=\"check|check2\""
output = subprocess.check_output(
command_line,
shell=True
)
lines = output.splitlines(True)
print lines
要实时查看进程的输出,请参阅:Getting realtime output using subprocess。
编辑: 这是使用 Popen 处理双引号的代码:
from subprocess import Popen, PIPE, STDOUT
command_line = 'ls -la | grep "wheel"'
p = Popen(command_line, stdout=PIPE, stderr=STDOUT, shell=True)
while True:
line = p.stdout.readline()
if not line:
break
else:
print line
您应该不使用shell=True
到运行一个bat
文件。如果必须 运行 某些内置的 shell 命令,则 仅 使用它。换句话说,您所做的使用是无用的,唯一的影响是增加程序的安全漏洞。
此外,请注意 documentation 明确指出,在使用 shell=True
时,建议将命令行作为字符串传递:
If shell is
True
, it is recommended to pass args as a string rather than as a sequence.
所以你应该这样做:
subprocess.check_output('runme.bat --include="check|check2"', shell=True)
如果您只关心输出,则应使用 check_output
函数。这比创建 Popen
对象然后手动读取输出要简单得多。
另请参阅 my answer,了解 shell=True
如何更改参数的含义。
在 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='')
stderr=subprocess.STDOUT
将 stderr 合并到 stdout。如果您设置 stderr=PIPE
那么您应该从 process.stderr
中读取 并行 并从 process.stdout
中读取,否则您的程序可能会死锁。
Popen()
将字符串传递给 CreateProcess()
Windows 函数。如果子进程实际上是一个批处理文件;您可能应该显式传递 shell=True
以明确该命令是使用 cmd.exe
规则解释的(^
、|
等是元字符,有关更多详细信息
如果您想使用 %1
而不是 %*
传递参数,以便它包含
整个 --include="check|check2"
(不仅是 --include
) 然后你可以在参数周围使用额外的引号作为
command = '"runme.bat" "--include="check^^^|check2""'
注意:三重 ^
转义 |
这里。