Python 子进程“类型错误:需要一个类似字节的对象,而不是‘str’”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44989808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 00:43:02  来源:igfitidea点击:

subprocess "TypeError: a bytes-like object is required, not 'str'"

pythonstringsubprocess

提问by chatbottest

I'm using this code from a previously asked question a few years ago, however, I believe this is outdated. Trying to run the code, I receive the error above. I'm still a novice in Python, so I could not get much clarification from similar questions. Does anyone know why this is happening?

我正在使用几年前先前提出的问题中的此代码,但是,我认为这已经过时了。尝试运行代码时,我收到上述错误。我仍然是 Python 的新手,所以我无法从类似的问题中得到太多的澄清。有谁知道为什么会这样?

import subprocess

def getLength(filename):
  result = subprocess.Popen(["ffprobe", filename],
    stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
  return [x for x in result.stdout.readlines() if "Duration" in x]

print(getLength('bell.mp4'))

Traceback

追溯

Traceback (most recent call last):
  File "B:\Program Files\ffmpeg\bin\test3.py", line 7, in <module>
    print(getLength('bell.mp4'))
  File "B:\Program Files\ffmpeg\bin\test3.py", line 6, in getLength
    return [x for x in result.stdout.readlines() if "Duration" in x]
  File "B:\Program Files\ffmpeg\bin\test3.py", line 6, in <listcomp>
    return [x for x in result.stdout.readlines() if "Duration" in x]
TypeError: a bytes-like object is required, not 'str'

回答by Martijn Pieters

subprocessreturns bytesobjects for stdout or stderr streams by default. That means you also need to use bytesobjects in operations against these objects. "Duration" in xuses strobject. Use a bytes literal (note the bprefix):

subprocessbytes默认情况下返回stdout 或 stderr 流的对象。这意味着您还需要bytes在针对这些对象的操作中使用对象。"Duration" in x使用str对象。使用字节文字(注意b前缀):

return [x for x in result.stdout.readlines() if b"Duration" in x]

or decode your data first, if you know the encoding used (usually, the locale default, but you could set LC_ALLor more specific locale environment variablesfor the subprocess):

或者首先解码您的数据,如果您知道使用的编码(通常是语言环境默认值,但您可以为子进程设置LC_ALL或更具体的语言环境环境变量):

return [x for x in result.stdout.read().decode(encoding).splitlines(True)
        if "Duration" in x]

The alternative is to tell subprocess.Popen()to decode the data to Unicode strings by setting the encodingargument to a suitable codec:

另一种方法是subprocess.Popen()通过将encoding参数设置为合适的编解码器来告诉将数据解码为 Unicode 字符串:

result = subprocess.Popen(
    ["ffprobe", filename],
    stdout=subprocess.PIPE, stderr = subprocess.STDOUT,
    encoding='utf8'
)

If you set text=True(Python 3.7 and up, in previous versions this version is called universal_newlines) you also enable decoding, using your system default codec, the same one that is used for open()calls. In this mode, the pipes are line buffered by default.

如果您设置text=True(Python 3.7 及更高版本,在以前的版本中,此版本称为universal_newlines),您还可以使用系统默认编解码器启用解码,这与用于open()调用的编解码器相同。在这种模式下,管道默认是行缓冲的。

回答by Harshith Thota

Like the errror says, "Duration" is a string. Whereas, the X is a byte like object as results.stdout.readlines()reads the lines in the output as bytecode and not string.

就像错误所说的那样,“持续时间”是一个字符串。而 X 是一个类似字节的对象,因为results.stdout.readlines()将输出中的行读取为字节码而不是字符串。

Hence store "Duration" in a variable, say str_var and encode it into a byte array object using str_var.encode('utf-8').

因此将“持续时间”存储在一个变量中,比如 str_var 并使用str_var.encode('utf-8').

Refer to [this][1].

请参阅[此][1]。

[1] : Best way to convert string to bytes in Python 3?

[1]:在 Python 3 中将字符串转换为字节的最佳方法?