错误:无法在类似字节的对象上使用字符串模式

11

我正在使用Python正则表达式来显示连接到计算机的所有互联网无线配置文件。在我的倒数第二行中出现错误(TypeError: cannot use a string pattern on a bytes-like object),请帮忙识别我的错误。谢谢。

我的程序

import subprocess,re
command = "netsh wlan show profile"
output = subprocess.check_output(command, shell=True)  
network_names = re.search("(Profile\s*:\s)(.*)", output)  
print(network_names.group(0))

错误

line 8, in <module>


 return _compile(pattern, flags).search(string)


TypeError: cannot use a string pattern on a bytes-like object

你可以尝试在re.search中使用str(output),或者使用output.decode('utf-8'),也许会有帮助? - Chris
2
output = output.decode()subprocess返回的是bytes类型,你需要手动转换为string/unicode(使用默认的'utf-8'编码或其他编码 - 例如decode('latin1') - 如果系统使用不同于utf-8的编码)。 - furas
3个回答

20

Python 3区分“bytes”和“string”类型;这对于Unicode字符串特别重要,其中每个字符的大小取决于字符和编码。

正则表达式可以在两者上运行,但必须保持一致-在字节中搜索字节,在字符串中搜索字符串。

根据您的需要,有两种解决方案:

  • 在搜索之前解码output变量;例如:使用output_text = output.decode('utf-8')

    这取决于您正在使用的编码方式;UTF-8是当今最常用的编码方式。

    匹配组将是一个字符串。

  • 通过在正则表达式前添加b前缀来使用字节进行搜索。正则表达式也应使用r前缀,因此它变为:re.search(br"(Profile\s*:\s)(.*)", output)

    匹配组将是一个字节对象。


1
在搜索之前对输出变量进行解码对我很有帮助。 - 0xsteve

3

根据 Popen.stdout 的文档:

如果 stdout 参数为 PIPE,则该属性是一个可读流对象,就像 open() 返回的那样。从该流中读取提供了子进程的输出。如果指定了 encoding 或 errors 参数或 universal_newlines 参数为 True,则该流是文本流,否则它是字节流。如果 stdout 参数不是 PIPE,则该属性为 None。

因此,如果没有设置这些选项,您将得到一个字节流。

subprocess.check_output 支持一个 encoding 关键字参数。将其设置为 'utf8',您将获得一个文本流:

output = subprocess.check_output(command, shell=True, encoding='utf8')

0

我在我的电脑上使用Python 2.7尝试了相同的代码。完美运行。

输出是一个字符串对象。

我认为你可以在这段代码“output = subprocess.check_output(command, shell=True)”后面添加一行代码“print(type(output))”。

你可以看到真正的数据类型,如果不是字符串,请尝试使用“output = str(output)”将其转换为字符串。


Python 2将bytes视为string,但Python 3不将bytes视为string - furas
所以我说使用str方法将其转换为字符串。 - Zhd Zilin
1
使用 output = str(output) 的缺点是 (a) 它会在文本周围添加 b'' 标记,(b) 它对带重音符号的字符、表情符号等处理效果不佳。例如,它会打印出 b'caf\xc3\xa9' 而不是 café。使用 .decode() 方法可以正确处理所有这些字符。 - Jiří Baum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接