首页 文章

subprocess stdout字符串解码不起作用

提问于
浏览
0

我一口打印,它立即打印在命令行上,它在一段时间内生成多行 . 该工具为bs1770gain,命令为"path\to\bs1770gain.exe" "-i" "\path\to\audiofile.wav",通过使用--loglevel参数,您可以包含更多数据,但无法删除写入stdout的渐进结果 .

我需要stdout来返回一个人类可读的字符串(因此stdout_formatted操作):

with subprocess.Popen(list_of_args, stdout=subprocess.PIPE,  stderr=subprocess.PIPE) as proc:
    stdout, stderr = proc.communicate()
    stdout_formatted = stdout.decode('UTF-8')
    stderr_formatted = stderr.decode('UTF-8')

但是,如果我打印它,我只能将变量视为人类可读的字符串,例如

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

仔细观察,人类可读的字符在字符串中(第一个字是“分析”

我猜测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) .

我现在紧紧 grab 稻草 - 当在变量中调用print或者删除stdout字符串中不需要的字节码时,是否可以捕获控制台中显示的内容?

2 回答

  • 4

    您没有UTF-8数据 . 你有UTF-16数据 . UTF-16为每个字符使用两个字节; ASCII和Latin-1范围内的字符(例如 a )仍然使用2个字节,但其中一个字节始终是 \x00 NUL字节 .

    因为UTF-16总是为每个字符使用2个字节,所以它们的顺序开始重要 . 编码器可以在两个选项之间进行选择;一个被称为Little Endian, the other Big Endian . 通常,编码器在一开始就包括Byte Order Mark,以便解码器知道解码时要使用的两个顺序选项中的哪一个 .

    您发布的数据没有 0xFF0xFE 字节,但您的数据确实看起来像是使用little-endian排序 . 这适合于Windows; Windows总是使用little-endian排序来获得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'
    
  • -2

    你有没有尝试过 :

    str(stdout_formatted).replace('\x00','')
    

相关问题