如何修改函数使subprocess.Popen输出处理兼容Python2与Python3
解决Python2/3兼容的进程检查函数错误问题
这个问题的核心是Python 2和3对subprocess输出的处理差异——Python 3中subprocess.PIPE返回的是字节对象(bytes),而Python 2中返回的是字符串(str)。你之前只修改了换行分隔符为b"\n",但program参数和"defunct"还是字符串类型,和字节类型的line对比自然会抛出TypeError。
下面提供两种简洁的兼容方案:
方案1:使用universal_newlines=True统一文本模式
这是最省心的方案,直接让subprocess以文本模式返回输出,不管Python 2还是3,拿到的都是字符串,完全避免字节/字符串的类型冲突:
import subprocess def running(program): # universal_newlines=True 让输出以字符串形式返回(兼容Python2/3) results = subprocess.Popen( ["ps", "-A"], stdout=subprocess.PIPE, universal_newlines=True ).communicate()[0].split("\n") # 所有变量都是字符串,对比逻辑完全正常 matches_current = [line for line in results if program in line and "defunct" not in line] return bool(matches_current)
说明:universal_newlines=True(Python 3.7+也可写text=True,但为了兼容Python2建议用前者)会让subprocess把标准输出当作文本流处理,自动将字节解码为字符串,让两个版本的行为完全一致。
方案2:手动统一字节/字符串类型
如果不想依赖文本模式,可以手动处理类型差异,确保对比的两边类型一致:
import subprocess import sys def running(program): output = subprocess.Popen( ["ps", "-A"], stdout=subprocess.PIPE ).communicate()[0] # 根据Python版本转换输出类型 if sys.version_info >= (3, 0): # Python3:字节转字符串(用系统默认编码或指定utf-8) results = output.decode("utf-8").split("\n") else: # Python2:直接使用字符串输出 results = output.split("\n") matches_current = [line for line in results if program in line and "defunct" not in line] return bool(matches_current)
或者也可以统一转成字节类型进行对比:
import subprocess import sys def running(program): output = subprocess.Popen( ["ps", "-A"], stdout=subprocess.PIPE ).communicate()[0] results = output.split(b"\n") # 将对比的字符串统一转为字节 if sys.version_info >= (3, 0): program_bytes = program.encode("utf-8") defunct_bytes = b"defunct" else: # Python2中str和bytes是同一类型,直接使用原字符串 program_bytes = program defunct_bytes = "defunct" matches_current = [line for line in results if program_bytes in line and defunct_bytes not in line] return bool(matches_current)
测试验证
两种方案都能让running("top")在Python2和Python3中正常返回布尔值,不会再抛出TypeError。
内容的提问来源于stack exchange,提问作者BlandCorporation
相关产品推荐
相关产品推荐

