从S3桶复制JSON文件至另一S3桶时文件未被识别问题求助
问题排查与解决方案
针对你用AWS Glue复制S3 JSON文件出现异常的情况,从代码和场景出发,常见问题点及解决方法如下:
1. 文件名大小写导致部分文件未被读取
你的文件中有.Json(大写J)后缀的文件,而Glue默认读取JSON格式时,只会匹配小写.json后缀的文件,这会导致03-12.Json、04-12.Json、05-12.Json这三个文件未被加载。
验证方法:在读取动态框架后添加计数代码,检查加载的记录数是否符合预期:
print("加载的记录数:", AmazonS3_node1664415190345.count())
如果计数远小于实际文件中的数据量,说明确实有文件未被读取。
解决方法:
修改读取的connection_options,用通配符匹配大小写后缀:
connection_options={ "paths": ["s3://xxx-xxxx-yy/test/*.json", "s3://xxx-xxxx-yy/test/*.Json"], "recurse": True, },
或者直接指定具体文件名:
connection_options={ "files": ["02-12.json", "03-12.Json", "04-12.Json", "05-12.Json"], "paths": ["s3://xxx-xxxx-yy/test/"], },
2. Glue写入逻辑不符合“复制原文件”的需求
当前代码是读取JSON内容后重新序列化写入,这种方式会生成Spark默认的输出文件(如part-00000-xxxx.json),而不是保留原文件名和原文件结构,这可能就是你看到的“异常结果”。
如果你的需求是完整复制原文件(保留文件名和格式),不需要解析JSON内容,那么用Glue做这个事完全没必要,推荐更高效的方式:
- 使用AWS CLI命令直接复制:
aws s3 cp s3://xxx-xxxx-yy/test/ s3://xxx-yyyy-www/yyyy/ff/ --recursive
- 在Glue代码中调用Boto3执行S3对象复制(保留原文件名):
import boto3 s3 = boto3.client('s3') source_bucket = 'xxx-xxxx-yy' target_bucket = 'xxx-yyyy-www' source_prefix = 'test/' target_prefix = 'yyyy/ff/' # 列出源路径下的所有文件 response = s3.list_objects_v2(Bucket=source_bucket, Prefix=source_prefix) for obj in response['Contents']: source_key = obj['Key'] # 跳过文件夹(如果有) if source_key.endswith('/'): continue target_key = target_prefix + source_key.split('/')[-1] # 复制对象 s3.copy_object( Bucket=target_bucket, Key=target_key, CopySource={'Bucket': source_bucket, 'Key': source_key} )
3. Multiline配置与JSON文件格式不匹配
你设置了multiline: False,这个配置要求每个JSON对象单独占一行。如果你的JSON文件是多行格式(比如单个文件是一个JSON数组,或单个对象跨多行),会导致读取失败,数据无法正确加载。
解决方法:
检查JSON文件格式,如果是多行结构,将format_options改为:
format_options={"multiline": True},
4. Glue角色权限不足
确保Glue作业使用的IAM角色拥有以下权限:
- 源S3桶的
s3:GetObject、s3:ListBucket权限 - 目标S3桶的
s3:PutObject、s3:ListBucket权限
可以在IAM控制台检查角色的权限策略,补充对应的S3权限。
内容的提问来源于stack exchange,提问作者sthambi
相关产品推荐
相关产品推荐

