Python3.8通过boto3从Amazon S3读取.pkl文件出现类型错误如何解决?
问题分析与修复方案
报错触发原因
两个核心问题共同导致报错:
- S3 API调用错误:你混淆了boto3 S3客户端的两个接口:
download_fileobj()无返回值,作用是将S3对象内容写入你传入的第三个参数(可写类文件对象),你调用时未传该参数,还尝试访问返回值的['Body']属性,本身逻辑就不成立。- 你预期的返回带
Body字段的响应的接口是get_object(),而非download_fileobj()。
- pickle方法参数类型不匹配:如果前面的接口调用错误导致你拿到的返回值类型不是预期的bytes,再加上如果误用
pickle.loads()接收BytesIO对象,就会触发你看到的expected str, bytes or os.PathLike object, not _io.BytesIO报错(pickle.loads()要求传入bytes类型,pickle.load()才要求传入类文件对象)。
修复方案
方案1:使用get_object接口修复(更简单)
直接修改S3Mgr类的retrieveModel方法,替换错误的API调用:
def retrieveModel(self,fileName): self.__connect() # 替换download_fileobj为get_object resp = self.s3.get_object(Bucket=self.bucketName, Key="fcm/project/"+str(fileName)) return resp['Body'].read()
后续加载代码可以简化,不需要额外包装BytesIO:
import pickle S3obj = S3Mgr("mybucket") model_bytes = S3obj.retrieveModel("model.pkl") model = pickle.loads(model_bytes) prediction = model.predict(inputArray)
方案2:使用download_fileobj接口修复
如果要保留用download_fileobj的写法,调整如下:
from io import BytesIO # 修改S3读取方法 def retrieveModel(self,fileName): self.__connect() buffer = BytesIO() # 传入BytesIO对象承接内容 self.s3.download_fileobj(Bucket=self.bucketName, Key="fcm/project/"+str(fileName), Fileobj=buffer) buffer.seek(0) return buffer
后续加载代码:
import pickle S3obj = S3Mgr("mybucket") model_buffer = S3obj.retrieveModel("model.pkl") model = pickle.load(model_buffer) prediction = model.predict(inputArray)
内容的提问来源于stack exchange,提问作者codezero
相关产品推荐
相关产品推荐

