子进程“TypeError:需要一个类似字节的对象,而不是'str'"
问题描述
我正在使用 几年前提出的问题中的这段代码,但是,我认为这已经过时了.尝试运行代码,我收到上面的错误.我仍然是 Python 的新手,所以我无法从类似的问题中得到太多的澄清.有谁知道为什么会这样?
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?
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 (most recent call last):
File "B:Program Filesffmpegin est3.py", line 7, in <module>
print(getLength('bell.mp4'))
File "B:Program Filesffmpegin est3.py", line 6, in getLength
return [x for x in result.stdout.readlines() if "Duration" in x]
File "B:Program Filesffmpegin est3.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'
解决方案
subprocess
默认为 stdout 或 stderr 流返回 bytes
对象.这意味着您还需要在针对这些对象的操作中使用 bytes
对象."Duration" in x
使用 str
对象.使用字节文字(注意 b
前缀):
subprocess
returns bytes
objects for stdout or stderr streams by default. That means you also need to use bytes
objects in operations against these objects. "Duration" in x
uses str
object. Use a bytes literal (note the b
prefix):
return [x for x in result.stdout.readlines() if b"Duration" in x]
或首先解码您的数据,如果您知道使用的编码(通常是语言环境默认设置,但您可以 为子进程设置 LC_ALL
或更具体的语言环境变量):
or decode your data first, if you know the encoding used (usually, the locale default, but you could set LC_ALL
or more specific locale environment variables for the subprocess):
return [x for x in result.stdout.read().decode(encoding).splitlines(True)
if "Duration" in x]
另一种方法是通过将 encoding
参数设置为合适的编解码器来告诉 subprocess.Popen()
将数据解码为 Unicode 字符串:
The alternative is to tell subprocess.Popen()
to decode the data to Unicode strings by setting the encoding
argument to a suitable codec:
result = subprocess.Popen(
["ffprobe", filename],
stdout=subprocess.PIPE, stderr = subprocess.STDOUT,
encoding='utf8'
)
如果您设置 text=True
(Python 3.7 及更高版本,在以前的版本中,此版本称为 universal_newlines
),您还可以使用 系统默认编解码器,和open()
调用.在这种模式下,管道默认是行缓冲的.
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.
相关文章