首页 文章

代码适用于Python 2但不适用于Python3 TypeError:需要类似字节的对象,而不是'str'

提问于
浏览
1

以下代码适用于Python 2.7:

import os
import pickle

modelpath = "models/"

gmm_files = [os.path.join(modelpath,fname) for fname in 
          os.listdir(modelpath) if fname.endswith('.gmm')]

models    = [pickle.load(open(fname,'r')) for fname in gmm_files]

但是,当我在Python3中运行代码时,我从最后一行得到以下错误:

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

为了获得更好的想法,我尝试在两个版本中打印 print([type(open(fname,'r')) for fname in gmm_files]) 并发现在python 2中类型为 <type 'file'> ,在Python 3中类型为 <class '_io.TextIOWrapper'> .

我已经检查了这些stackoverflow问题,但他们都没有对此有用的答案:

python 3.5: TypeError: a bytes-like object is required, not 'str' when writing to a file

Python sockets error TypeError: a bytes-like object is required, not 'str' with send function

UPDATE

这里的一堆答案说将 open(fname, 'r') 更改为 open(fname, 'rb') ,但这只会导致另一个错误: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc0 in position 0: ordinal not in range(128)

2 回答

  • 2

    正如 pickle.load 方法的documentation所说(强调我的):

    参数文件必须有两个方法,一个采用整数参数的read()方法和一个不需要参数的readline()方法 . 两种方法都应返回字节 .

    open(stuff, 'r') 将打开文件以读取文本,而不是原始字节 . 因此, open(stuff, 'r').read 将返回 str ,而不是 bytes . 要解决此问题,请以二进制模式打开文件: open(stuff, 'rb') .

  • 1

    Ref https://docs.python.org/3.6/library/pickle.html#pickle.load,传递给 pickle.load 的类文件对象需要返回二进制数据 . 默认情况下,文件以文本模式打开,这就是您看到此错误的原因 . 如果以二进制模式打开文件(通过将 'b' 添加到模式),一切都应该有效 .

    例如 .

    models = [pickle.load(open(fname, 'rb')) for fname in gmm_files]
    

相关问题