AWS Glue Python Shell任务中读取Athena数据库

问题

怎样在AWS Glue Python Shell任务中读取Athena数据库中的数据

通过awswrangler读取

Python

python 复制代码
import pandas as pd
import boto3
import awswrangler as wr

....
def read_data_via_athena(database, table_name, start_ts, end_ts):
    """
    使用 Athena 解决大数据量下的内存问题
    """
    # 1. 编写 SQL。在服务端完成过滤,只拉取需要的列和行
    # 建议显式写出需要的列名,如 SELECT id, created_at, user_id ... 替代 SELECT *
    sql = f"""
    SELECT * FROM "{table_name}"
    WHERE created_at >= {start_ts} 
      AND created_at < {end_ts}
    """
    
    logger.info(f"正在执行 Athena 查询,筛选表 {table_name} 的数据...")
    
    try:
        # 2. 执行查询并直接获取 DataFrame
        batch_iterator = wr.athena.read_sql_query(
            sql=sql,
            database=database,
            ctas_approach=False,
            chunksize=5000,
            keep_files=False # 查询完自动清理临时文件
        )
        return batch_iterator

    except Exception as e:
        logger.error(f"Athena 查询异常: {str(e)}")
        raise

调用使用代码(这里就通过aw从数据湖里面读出了pandas数据):

python 复制代码
# 从 Glue Catalog 读取三个表的数据(表名完全由参数控制)
    tables = {
        table_summit: 'summit',
        table_summit_device: 'summit_device',
        table_summit_user: 'summit_user'
    }
    total_pushed_count = 0
    batch_size_push = 100  # API 每次接收的记录数
    
    for glue_table, type_name in tables.items():
        logger.info(f"开始处理表: {glue_table}")
        
        # 1. 获取 Athena 迭代器 (每批从 Athena 取 50000 行)
        batch_iterator = read_data_via_athena(database_name, glue_table, start_ts, end_ts)
        
        for idx, df_chunk in enumerate(batch_iterator, start=1):
            if df_chunk.empty:
                continue
                
            logger.info(f"表 {glue_table} - 正在处理 Athena 第 {idx} 批数据,行数:{len(df_chunk)}")
            
            # 2. 将这 5000 行转换为记录列表
            chunk_records = convert_dataframe_to_records(df_chunk, type_name)


            # --- 💡 新增:打印前 10 条数据进行查看 ---
            if idx == 1:  # 只在每个表的第一批次打印,避免日志刷屏
                logger.info(f"🔍 检查表 {glue_table} 的前 10 条数据样本:")
                sample_data = chunk_records[:10]
                # 使用 json.dumps 让打印出的 JSON 格式更漂亮(缩进2格)
                print(json.dumps(sample_data, indent=2, ensure_ascii=False))
            # ---------------------------------------
            
            # 3. 针对这一批记录,再切分成 100 条一组的小批次推送到 API
            for i in range(0, len(chunk_records), batch_size_push):
                mini_batch = chunk_records[i : i + batch_size_push]
                # 计算当前进度
                current_batch_end = i + len(mini_batch)
                
                try:
                    # TODO 此处模拟推送数据到第三方系统
                     logger.info(f"[{glue_table}] 正在处理 Athena 第 {idx} 块: 进度 {current_batch_end}/{len(chunk_records)} 条 | 总计已推送: {total_pushed_count + len(mini_batch)}")
                    total_pushed_count += len(mini_batch)
                    
                    # 控制推送频率
                    if send_delay > 0:
                        time.sleep(send_delay)
                except Exception as e:
                    logger.error(f"表 {glue_table} 数据推送失败: {e}")
                    raise # 根据业务需求决定是跳过还是中断
            
            # 💡 重要:手动清理当前 chunk 占用的内存(可选,但推荐)
            del chunk_records
            del df_chunk

    elapsed = (datetime.now() - start_time).total_seconds()
    logger.info(f"作业全部完成!总计成功推送: {total_pushed_count} 条,总耗时 {elapsed:.2f} 秒")

数据处理函数(这部分代码根据你的业务来处理):

python 复制代码
import datetime
import decimal

def convert_dataframe_to_records(df: pd.DataFrame, table_type: str) -> List[dict]:
    """将 DataFrame 转换为字典列表,处理所有不可 JSON 序列化的类型"""
    records = df.to_dict(orient='records')
    for rec in records:
        rec['add_table'] = table_type
        for k, v in list(rec.items()):
            if pd.isna(v):
                rec[k] = None
            # 💡 增加对 datetime.date 和 datetime.datetime 的统一处理
            elif isinstance(v, (pd.Timestamp, datetime.datetime, datetime.date)):
                rec[k] = v.isoformat()
            # 💡 针对 Decimal 类型(如 gps_latitude)也建议处理一下,防止后续报错
            elif hasattr(v, 'to_eng_string'): 
                rec[k] = float(v)
    return records
相关推荐
landyjzlai16 小时前
蓝迪哥玩转Ai(8)---端侧AI:RK3588 端侧大语言模型(LLM)开发实战指南
人工智能·python
S1998_1997111609•X17 小时前
论当今社会主义与人文关怀人格思想下的恶意仿生注入污染蜜罐描述进行函数值非法侵入爬虫的咼忄乂癿〇仺⺋.
数据库·网络协议·百度·ssh·开闭原则
我叫黑大帅17 小时前
如何通过 Python 实现招聘平台自动投递
后端·python·面试
其实防守也摸鱼18 小时前
CTF密码学综合教学指南--第九章
开发语言·网络·python·安全·网络安全·密码学·ctf
砚底藏山河18 小时前
Python量化开发:2026最佳实时股票数据API接口推荐与对比
开发语言·windows·python
倔强的石头_18 小时前
kingbase备份与恢复实战(六)—— 备份自动化与保留策略:Windows任务计划+日志追溯
数据库
研究点啥好呢19 小时前
专为求职者开发的“面馆”!!!摆脱面试焦虑!!!
python·面试·开源·reactjs·求职招聘·fastapi
轻刀快马19 小时前
别被 ORM 框架宠坏了:从一场“订单消失”悬案,看懂 MySQL 为什么要强推 InnoDB
数据库·mysql
DFT计算杂谈19 小时前
自动化脚本一键绘制三元化合物相图
java·运维·服务器·开发语言·前端·python·自动化
EW Frontier20 小时前
6G ISAC新范式:基于智能漏波天线的Wi‑Fi通感一体化系统设计与实测【附MATLAB+python代码】
开发语言·python·matlab·music·isac·doa·wi‑fi