如何用Python提取ADODB Recordset并导出为Pandas DataFrame
解决ADODB.Recordset转带动态表头的Pandas DataFrame问题
先提一句:你现有代码里初始化Excel的部分完全没用,删掉能节省不少资源。下面给两个靠谱的方案,直接解决动态表头的问题:
方案一:直接从Recordset提取表头+批量读取(最优方案)
这个方法不需要依赖Excel,直接通过ADODB的API提取表头和数据,效率最高,完美适配动态列:
import win32com.client import pandas as pd # 创建并打开数据库连接 conn = win32com.client.Dispatch('ADODB.Connection') cmd = win32com.client.Dispatch('ADODB.Command') DSN = 'Provider=MSDataShape;Data Provider=IBMDA400;Data Source="source"; User Id="user"; Password="password";' conn.Open(DSN) # 执行查询命令 cmd.ActiveConnection = conn cmd.CommandText = 'SELECT * FROM table LIMIT 100' RS = win32com.client.Dispatch('ADODB.Recordset') RS.Open(cmd) # 提取动态表头:遍历Recordset的字段集合获取列名 headers = [field.Name for field in RS.Fields] # 批量读取数据:GetRows返回列优先的二维数组,转置后适配DataFrame的行结构 data = RS.GetRows() data_transposed = list(zip(*data)) # 生成带表头的DataFrame df = pd.DataFrame(data_transposed, columns=headers) # 关闭资源,避免内存泄漏 RS.Close() conn.Close() # 验证结果 print(df.head())
关键说明:
- 用
RS.Fields遍历所有字段,直接取Name属性就是数据库返回的列名,完全支持动态表头 GetRows()是ADODB提供的批量读取方法,比逐行循环读取效率高N倍,数据量大的时候优势明显- 因为
GetRows()返回的是(列数, 行数)的数组,所以用zip(*data)转置成(行数, 列数)的结构,直接传给DataFrame即可
方案二:借助Excel中转(适合需联动Excel的场景)
如果你的业务场景需要同时操作Excel,也可以用CopyFromRecordset写入数据后再读取成DataFrame:
import win32com.client import pandas as pd # 初始化Excel后台运行(不显示界面) Excel = win32com.client.gencache.EnsureDispatch('Excel.Application') Excel.Visible = False wb = Excel.Workbooks.Add() ws = wb.ActiveSheet # 创建并打开数据库连接 conn = win32com.client.Dispatch('ADODB.Connection') cmd = win32com.client.Dispatch('ADODB.Command') DSN = 'Provider=MSDataShape;Data Provider=IBMDA400;Data Source="source"; User Id="user"; Password="password";' conn.Open(DSN) cmd.ActiveConnection = conn cmd.CommandText = 'SELECT * FROM table LIMIT 100' RS = win32com.client.Dispatch('ADODB.Recordset') RS.Open(cmd) # 先手动写入表头到Excel第一行 for i, field in enumerate(RS.Fields): ws.Cells(1, i+1).Value = field.Name # 把Recordset指针移回开头,再写入数据 RS.MoveFirst() ws.Range('A2').CopyFromRecordset(RS) # 从Excel读取成带表头的DataFrame df = pd.DataFrame(ws.UsedRange.Value[1:], columns=ws.UsedRange.Value[0]) # 清理资源 RS.Close() conn.Close() wb.Close(SaveChanges=False) Excel.Quit() print(df.head())
关键说明:
CopyFromRecordset本身不会自动写入表头,必须手动遍历字段集合写入第一行- 这个方案多了Excel的开销,纯数据处理优先选方案一,仅当需要和Excel联动时使用
内容的提问来源于stack exchange,提问作者Ryan Dray
相关产品推荐
相关产品推荐

