如何在Python 2和Python 3中处理subprocess.Popen输出

时间:2018-01-09 13:50:39

标签: string python-3.x unicode subprocess

我有一个简单的函数,用于检查程序是否正在运行并根据需要返回一个布尔值。它通过使用模块ps -A检查命令subprocess的输出来完成此操作。我试图让这个函数在Python 2和Python 3中都能正常工作但遇到以下错误:

TypeError: a bytes-like object is required, not 'str'

如何更改函数,以便它可以在两个 Python 2和Python 3中工作?

import subprocess

def running(program):
    results = subprocess.Popen(
        ["ps", "-A"],
        stdout = subprocess.PIPE
    ).communicate()[0].split("\n")
    matches_current = [
        line for line in results if program in line and "defunct" not in line
    ]
    if matches_current:
        return True
    else:
        return False
编辑:在@Josh的一些指导下,我已经将换行符字符串分隔符更改为字节码,但是我仍然遇到类似的问题:

>>> import subprocess
>>> def running(program):
...     results = subprocess.Popen(
...         ["ps", "-A"],
...         stdout = subprocess.PIPE
...     ).communicate()[0].split(b"\n")
...     matches_current = [
...         line for line in results if program in line and "defunct" not in line
...     ]
...     if matches_current:
...         return True
...     else:
...         return False
... 
>>> running("top")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in running
  File "<stdin>", line 7, in <listcomp>
TypeError: a bytes-like object is required, not 'str'

3 个答案:

答案 0 :(得分:1)

使用b"\n"之类的字节串而不是普通"\n",并使用program.encode()代替program(假设您正在传递字符串):< / p>

results = subprocess.Popen(
    ["ps", "-A"],
    stdout = subprocess.PIPE
).communicate()[0].split(b"\n")
matches_current = [
    line for line in results if program.encode() in line and b"defunct" not in line
]

这是因为在Python 3中,subprocess.Popen.communicate默认返回字节而不是字符串。在Python 2.6+中,b"\n" == "\n",所以你不应该有任何问题。

答案 1 :(得分:0)

这是一个古老的问题,但是我发现了一种更简单的方法可以在Python 2和3中使用:在.decode()之后添加communicate()[0]

results = subprocess.Popen(
        ["ps", "-A"],
        stdout = subprocess.PIPE
    ).communicate()[0].decode().split("\n")

因此,您不必在每个字符串文字或b之前添加encode()到代码中的字符串变量。另外,results将成为Unicode字符串。

PS。就我而言,我有subprocess.check_output()并附加了.decode()也按预期工作。

编辑:也许最好指定编码,例如decode('utf-8'),以防万一。

答案 2 :(得分:0)

universal_newlines=True 生成字符串而不是字节。

results = subprocess.Popen(
        ["ps", "-A"],
        stdout = subprocess.PIPE,
        universal_newlines=True
    ).communicate()[0].split("\n")

使用迭代器

p = subprocess.Popen(
        ["ps", "-A"],
        stdout = subprocess.PIPE,
        universal_newlines=True
    )
for result in p.stdin:
    print(result.strip())