windows os.popen().read()- charmap解码错误

ghhkc1vu  于 2023-10-22  发布在  Windows
关注(0)|答案(4)|浏览(149)

我已经读过UnicodeDecodeError: 'charmap' codec can't decode byte X in position Y: character maps to 了。虽然错误消息相似,但代码完全不同,因为我在这个问题中使用了os.popen,而不是open。我不能用其他问题的答案来解决这个问题。

output = os.popen("dir").read()

这一行,这是应该分配命令的输出“dir”到变量“输出”,是导致这个错误:

'charmap' codec can't decode byte 0x88 in position 260: character maps to <undefined>

我认为这可能是因为文件夹中的某些文件在其名称中包含**,,ć**等字母。但我不知道该怎么解决。

yc0p9oo0

yc0p9oo01#

os.popen只是subprocess.Popen的一个 Package 器,沿着一个io.TextIOWrapper对象:
返回的文件对象读取或写入文本字符串而不是字节。
如果Python的默认编码对你不起作用,你应该直接使用subprocess.Popen
潜在的问题是,默认情况下,即使输出到管道,cmd也会写入ansi垃圾。此行为可能取决于您的Windows版本。
您可以通过将/U标志传递给cmd来修复此问题:

p = subprocess.Popen('cmd /u /c dir', stdout=subprocess.PIPE)
result = p.communicate()
text = result[0].decode('u16')
bfnvny8b

bfnvny8b2#

在这种情况下,使用subprocess.Popen太笼统、太冗长、太难记。使用subprocess.check_output代替。
它返回一个bytes对象,可以使用decode函数将其转换为str

import subprocess
x = subprocess.check_output(['ls','/'])
print(x.decode('utf-8'))

在线试用!

pgx2nnw8

pgx2nnw83#

如果有人像我一样在python 2中使用了 with-语句和readline()的组合(用于Windows中的timezone Util),那么它对python3不起作用:

with os.popen("tzutil /l") as source:
    key, value = self.get_key_value(source, True)
    while value and key:
        timezones_to_json.append({u"key": key, u"value": value, u"toolTip": key})
        key, value = self,get_key_value(source, False)
return timezones_to_json

def get_key_value(self, source, first=False):
    if not first:
        source.readline()
    value = source.stdout.readline().strip()
    key = source.stdout.readline().strip()
    return key, value

所以我对python3的修改是:
1.就像@Josh Lee说的那样,我使用了子进程.Popen,但是我有一个AttributeError: __exit__
1.所以你必须在末尾插入.stdout,所以with-statement中的对象有__enter____exit__方法:

with subprocess.Popen(['tzutil', '/l'], stdout=subprocess.PIPE).stdout as source:
vngu2lb8

vngu2lb84#

经过一段时间的探索,我找到了这个解决方案:

import os
stream = os.popen("dir")
stream._stream.reconfigure(encoding='latin') # Now the stream is configured in the encoding 'latin'
data = stream.read()

这里我们使用os.popen对象的_stream属性来重新配置stream对象并读取字节。虽然这可能会让人觉得很奇怪,但这是我找到的唯一解决方案。
如果您有更好的解决方案,请编辑此答案!

相关问题