使用Python下载AWS S3 Bucket时遇OSError[Errno22]错误求助
解决S3 Bucket下载时的OSError: Errno 22 Invalid argument问题
问题根源
你遇到的错误核心原因有两个:一是S3对象的文件名包含了本地操作系统不允许的特殊字符(比如你例子里的冒号:,Windows系统明确禁止文件名使用这类符号);二是原代码没有处理Bucket中的层级目录结构——当S3对象的key包含子路径时,本地没有对应的目录,不仅会导致下载失败,还可能出现不同目录下的同名文件被覆盖的情况。
解决方案
我们需要针对这两个问题分别处理:
- 替换文件名中的非法字符,适配本地系统的命名规则
- 根据S3对象的key创建对应的本地目录,确保下载路径存在
修改后的完整代码
import os import boto3 from pathlib import Path def sanitize_filename(filename): # 定义常见的系统非法字符,可根据自己的操作系统调整 illegal_chars = '<>:"/\\|?*' for char in illegal_chars: filename = filename.replace(char, '-') return filename s3 = boto3.resource('s3') my_bucket = s3.Bucket('mys3bucket') for s3_object in my_bucket.objects.all(): # 用Path类优雅处理路径拆分 s3_path = Path(s3_object.key) # 清理文件名中的非法字符 sanitized_filename = sanitize_filename(s3_path.name) # 构建本地保存路径,完整保留S3的目录结构 local_path = Path('.') / s3_path.parent / sanitized_filename # 自动创建所有需要的父目录,不存在则创建,存在也不报错 local_path.parent.mkdir(parents=True, exist_ok=True) # 执行下载 my_bucket.download_file(s3_object.key, str(local_path))
代码细节说明
sanitize_filename函数:把文件名里的非法字符统一替换成-,你可以根据自己使用的系统(Linux/macOS限制更少)调整需要替换的字符列表。Path类的使用:相比os.path更直观,能轻松处理跨平台路径问题,mkdir(parents=True, exist_ok=True)可以一次性创建所有层级的目录,避免手动判断目录是否存在的麻烦。- 保留目录结构:确保S3 Bucket里的子目录在本地同步创建,彻底解决不同目录下同名文件被覆盖的问题。
内容的提问来源于stack exchange,提问作者Murthy P
相关产品推荐
相关产品推荐

