如何处理子流程.Python 2 和 Python 3 中的 Popen 输出



我有一个简单的函数,可以检查程序是否正在运行并根据需要返回布尔值。它通过使用模块subprocess ps -A检查命令的输出来做到这一点。我正在尝试让这个函数在 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'

使用像 b"n" 这样的字节串,而不仅仅是普通的"n",并且还使用 program.encode() 而不是 program(假设你被传递了一个字符串(:

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" ,所以你应该没有任何问题。

这是一个老问题,但我找到了一种在 Python 2 和 3 中都适用的更简单的方法:在 communicate()[0] 后添加 .decode()

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

因此,您不必在代码中的字符串变量的每个字符串文本或encode()之前添加 b 's。作为奖励,results将成为Unicode字符串。

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

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

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())

最新更新