String 子进程标准输出字符串解码不工作
我使用下面的子流程调用来使用命令行工具。命令行工具的输出不是一次性打印的,它会立即在命令行上打印,它会在一段时间内生成多行。该工具为,命令为“path\to\bs1770gain.exe”“-i”“\path\to\audiofile.wav”,通过使用--loglevel参数,可以包含更多数据,但不能删除写入stdout的渐进结果 我需要stdout返回一个人类可读的字符串(因此是stdout\u格式的操作): 但是,如果我打印变量,我只能将其视为人类可读的字符串String 子进程标准输出字符串解码不工作,string,python-3.x,utf-8,subprocess,ascii,String,Python 3.x,Utf 8,Subprocess,Ascii,我使用下面的子流程调用来使用命令行工具。命令行工具的输出不是一次性打印的,它会立即在命令行上打印,它会在一段时间内生成多行。该工具为,命令为“path\to\bs1770gain.exe”“-i”“\path\to\audiofile.wav”,通过使用--loglevel参数,可以包含更多数据,但不能删除写入stdout的渐进结果 我需要stdout返回一个人类可读的字符串(因此是stdout\u格式的操作): 但是,如果我打印变量,我只能将其视为人类可读的字符串 In [23]: print
In [23]: print(stdout_formatted )
nalyzing ... [1/2] "filename.wav":
integrated: -2.73 LUFS / -20.27 LU [2/2]
"filename2.wav":
integrated: -4.47 LUFS / -18.53 LU
[ALBUM]:
integrated: -3.52 LUFS / -19.48 LU done.
In [24]: stdout_formatted
Out[24]: 'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00g\.......
In [6]: stdout
Out[6]: b'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00g\......
In [4]: type(stdout)
Out[4]: bytes
In [5]: type(stdout_formatted)
Out[5]: str
如果仔细看,人类可读的字符在字符串中(第一个单词是“analysis”
我猜stdout值需要解码/编码,所以我尝试了不同的方法:
stdout_formatted.encode("ascii")
Out[18]: b'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00g
stdout_formatted.encode("utf-8")
Out[17]: b'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00g\
stdout.decode("utf-8")
Out[15]: 'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00g\
stdout.decode("ascii")
Out[14]: 'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00g\
bytes(stdout).decode("ascii")
Out[13]: 'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00g\
我使用了一个名为chardet的库来检查stdout的编码:
import chardet
chardet.detect(stdout)
Out[26]: {'confidence': 1.0, 'encoding': 'ascii', 'language': ''}
我在Windows 10上工作,并且一直在使用python 3.6(anaconda软件包及其集成的Spyder IDE)
我现在有点抓紧救命稻草了——在变量中调用print时,是否可以捕获控制台中显示的内容,或者删除stdout字符串中不需要的字节码?您是否尝试过:
str(stdout_formatted).replace('\x00','')
?您是否尝试过:
str(stdout_formatted).replace('\x00','')
?您没有UTF-8数据。您有UTF-16数据。UTF-16对每个字符使用两个字节;ASCII和拉丁-1范围内的字符(如
a
)仍然使用两个字节,但其中一个字节始终是\x00
NUL字节
因为UTF-16总是为每个字符使用2个字节,所以它们的顺序开始起作用。编码器可以在两个选项之间进行选择;一个被调用。通常,编码器在一开始就包含一个,以便解码器知道在解码时使用两个顺序选项中的哪一个
您发布的数据似乎不包含BOM(我看不到0xFF
和0xFE
字节,但您的数据看起来确实使用了小端排序。这与Windows相符;Windows总是对其UTF-16输出使用小端排序
如果您的数据确实存在BOM表,您可以将其解码为'utf-16'
。如果缺少BOM表,请使用'utf-16-le'
:
>>> sample = b'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00'
>>> sample.decode('utf-16-le')
'analyzin'
>>> import codecs
>>> (codecs.BOM_UTF16_LE + sample)
b'\xff\xfea\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00'
>>> (codecs.BOM_UTF16_LE + sample).decode('utf-16')
'analyzin'
您没有UTF-8数据。您有UTF-16数据。UTF-16对每个字符使用两个字节;ASCII和拉丁语-1范围内的字符(如
a
)仍然使用两个字节,但其中一个字节始终是\x00
NUL字节
因为UTF-16总是为每个字符使用2个字节,所以它们的顺序开始起作用。编码器可以在两个选项之间进行选择;一个被调用。通常,编码器在一开始就包含一个,以便解码器知道在解码时使用两个顺序选项中的哪一个
您发布的数据似乎不包含BOM(我看不到0xFF
和0xFE
字节,但您的数据看起来确实使用了小端排序。这与Windows相符;Windows总是对其UTF-16输出使用小端排序
如果您的数据确实存在BOM表,您可以将其解码为'utf-16'
。如果缺少BOM表,请使用'utf-16-le'
:
>>> sample = b'a\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00'
>>> sample.decode('utf-16-le')
'analyzin'
>>> import codecs
>>> (codecs.BOM_UTF16_LE + sample)
b'\xff\xfea\x00n\x00a\x00l\x00y\x00z\x00i\x00n\x00'
>>> (codecs.BOM_UTF16_LE + sample).decode('utf-16')
'analyzin'
您显示了
stdout
的类型
,但显示了stderr的打印输出。您是否看到这两种输出都存在相同的问题?感谢您指出这一点-代码中有一些拼写错误(我现在已修复)。我将重点放在stdout上,因为到目前为止,stderr上没有输出。它只是一个字符串类型的空白字符串“”。您能否提供参数列表
,以便我们重现问题?您显示了stdout
的类型
,但打印出的stderr
。您是否看到这两种输出都存在相同的问题谢谢你指出这一点-代码中有一些拼写错误(我现在已经纠正了)。我将重点放在stdout上,因为到目前为止,stderr上没有输出。它只是一个字符串类型的空白字符串“”。您能否提供参数列表
,以便我们重现问题?是的,恐怕它无法修复字符串。取而代之的是\x00"0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2@user3535074:看起来有东西在打印进度条。你正在运行什么命令?你能禁用进度信息吗?命令行工具的输出不是一次打印的,它先打印一行,然后打印下一行。工具是bs1770gain,命令是“path\to\bs1770gain.exe”“-i”“\path\to\audiofile.wav”@user3535074您可能希望将此添加到您的问题中,而不是添加到注释中,以便所有人都能看到它。@user3535074您还可以使用re:your_string=re.sub(r'\d+','',your_string)
删除该百分比部分。
是的,恐怕它无法修复字符串。取而代之的是\x00"0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%1%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2%2@user3535074:看起来有东西在打印进度条。你正在运行什么命令?你能禁用进度信息吗?命令行工具的输出不是一次打印的,它先打印一行,然后打印下一行。工具是bs1770gain,命令是“path\to\bs1770gain.exe”“-i”“\path\to\audiofile.wav”@user3535074您可能希望将此添加到您的问题中,而不是添加到注释中,以便每个人都能看到它。@user3535074您还可以使用re删除该百分比部分:your_string=re.sub(r'\d+','',your_string)
非常感谢您的详细回答-这解释了很多。字符串输出仍然包括(因为没有更好的词)已正确解码的人类可读字符串之间的“乱码”。命令行工具(bs1770gain-“path\to\bs1770gain.exe”“-i”“\path\to\audiofile.wav”将