使用DuckDB查询S3 Parquet文件时域名拼接错误求助
解决DuckDB访问S3 Parquet文件时的400 Bad Request错误
你遇到的400错误核心原因并非桶名拼接问题,而是DuckDB连接初始化时机与AWS凭证设置时机不匹配,同时可能缺失S3桶区域配置,导致请求验证失败。以下是具体解决方案:
关键问题分析
- DuckDB在创建连接时会读取AWS凭证信息,你当前是先创建连接再设置环境变量,导致连接未加载到STS获取的临时凭证,触发认证错误。
- 若S3桶不在默认的
us-east-1区域,未显式指定区域会导致请求路由错误,同样返回400。
修正后的代码示例
推荐两种可靠的凭证传递方式,二选其一即可:
方式一:先设置环境变量再创建DuckDB连接
import boto3 import duckdb import os # 获取STS临时凭证 sts_client = boto3.client('sts') assumed_role_object = sts_client.assume_role( RoleArn='arn:aws:iam::012345678901:role/my-role', RoleSessionName='role' ) credentials = assumed_role_object['Credentials'] # 先配置AWS环境变量(包括区域,替换为你的桶实际区域) os.environ['AWS_ACCESS_KEY_ID'] = credentials['AccessKeyId'] os.environ['AWS_SECRET_ACCESS_KEY'] = credentials['SecretAccessKey'] os.environ['AWS_SESSION_TOKEN'] = credentials['SessionToken'] os.environ['AWS_REGION'] = 'eu-west-1' # 替换为你的桶区域 # 再创建DuckDB连接 con = duckdb.connect() # 执行查询(假设query为读取Parquet的语句) query = 'SELECT * FROM read_parquet(?)' result = con.execute(query, ('s3://my-bucket/file.parquet',)).fetchall() print(result)
方式二:直接在DuckDB连接中配置凭证(推荐)
跳过环境变量,直接通过DuckDB的SET命令注入凭证,避免时机问题:
import boto3 import duckdb # 获取STS临时凭证 sts_client = boto3.client('sts') assumed_role_object = sts_client.assume_role( RoleArn='arn:aws:iam::012345678901:role/my-role', RoleSessionName='role' ) credentials = assumed_role_object['Credentials'] # 创建DuckDB连接后直接配置S3参数 con = duckdb.connect() con.execute(f""" SET s3_access_key_id = '{credentials['AccessKeyId']}'; SET s3_secret_access_key = '{credentials['SecretAccessKey']}'; SET s3_session_token = '{credentials['SessionToken']}'; SET s3_region = 'eu-west-1'; # 替换为你的桶区域 """) # 执行查询 query = 'SELECT * FROM read_parquet(?)' result = con.execute(query, ('s3://my-bucket/file.parquet',)).fetchall() print(result)
额外检查项
- 确认STS角色
my-role拥有访问目标S3桶的权限(s3:GetObject等) - 验证临时凭证的有效性(可通过
boto3调用S3 API测试) - 若仍报错,检查桶名是否包含特殊字符,或是否为路径样式访问的桶(需额外配置
SET s3_use_path_style = true;)
内容的提问来源于stack exchange,提问作者david backx
相关产品推荐
相关产品推荐

