使用Boto加载文件遇文件名过长错误及S3恢复词汇表问题求助
我来帮你一步步解决这两个问题:
问题1:从S3恢复VocabularyProcessor失败的解决方法
首先要明确:tf.contrib.learn.preprocessing.VocabularyProcessor.restore() 方法不直接支持S3路径,它默认只识别本地文件系统的路径,所以你直接传入s3://bucket/key格式的路径时,它会把这个路径当成本地文件去找,自然会报“对象不存在”的错误。
这里有两种可靠的解决方式:
方案1:先下载到本地临时文件再加载
用boto3把S3上的词汇表文件下载到本地临时文件,再用restore()加载这个本地路径。临时文件用完后可以删除,避免占用空间:
import tempfile import boto3 import os from tensorflow.contrib.learn.python.learn.preprocessing import VocabularyProcessor # 初始化S3客户端 s3 = boto3.client('s3') BUCKET_NAME = '你的存储桶名称' KEY = '词汇表文件在S3中的路径,比如vocab/vocab_processor.pkl' # 创建临时文件(delete=False避免上下文结束后自动删除) with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_local_path = temp_file.name # 从S3下载文件到临时路径 s3.download_file(BUCKET_NAME, KEY, temp_local_path) # 恢复词汇表 vocab_processor = VocabularyProcessor.restore(temp_local_path) # 可选:用完临时文件后删除 os.unlink(temp_local_path)
方案2:直接读取字节流用Pickle加载
VocabularyProcessor.save()本质是把对象序列化为Pickle格式,所以你可以直接读取S3对象的字节数据,用pickle.loads()反序列化恢复对象,省去本地文件的步骤:
import boto3 import pickle from tensorflow.contrib.learn.python.learn.preprocessing import VocabularyProcessor # 初始化S3资源 s3 = boto3.resource('s3') obj = s3.Object(BUCKET_NAME, KEY) # 读取S3对象的字节数据 vocab_serialized_data = obj.get()['Body'].read() # 反序列化恢复词汇表 vocab_processor = pickle.loads(vocab_serialized_data)
问题2:Boto加载长文件名报错的解决方案
这个报错本质是因为S3对对象键(即文件名/路径)的字节长度限制:S3对象键最大支持1024字节的UTF-8编码长度,超过这个值就会触发错误。这里有几个实用的解决思路:
- 缩短文件名:如果业务允许,直接简化文件名,去掉冗余的描述、重复字符或不必要的前缀。
- 用哈希值替代长文件名:对原长文件名计算MD5/SHA-1哈希值,用哈希值作为S3对象键,同时把原文件名存在对象的元数据中,方便后续识别:
import hashlib original_long_name = "这是一个非常长的文件名包含很多字符和描述信息示例.txt" # 计算MD5哈希作为对象键 object_key = hashlib.md5(original_long_name.encode('utf-8')).hexdigest() # 上传时附带原文件名到元数据 s3.put_object( Bucket=BUCKET_NAME, Key=object_key, Body=你的文件内容, Metadata={'original_filename': original_long_name} ) # 下载时获取原文件名 target_obj = s3.Object(BUCKET_NAME, object_key) original_filename = target_obj.metadata['original_filename'] - 拆分成长路径结构:把长文件名拆分成多层目录结构,比如把
"very-long-filename-with-many-details.txt"拆成"very-long/filename-with/many-details.txt",既规避单键长度限制,又保持路径的可读性。 - 检查编码问题:有些看似长度正常的文件名,因为包含多字节UTF-8字符(比如中文、特殊符号),实际字节数超过了1024。可以用
len(文件名.encode('utf-8'))检查字节长度,必要时转成ASCII兼容名称或简化特殊字符。
内容的提问来源于stack exchange,提问作者Mihir Patel
相关产品推荐
相关产品推荐

