使用Google Sheets API v4及batchUpdate写入DataFrame遇序列化错误求助
解决Google Sheets API batchUpdate中的int64序列化错误
这个问题的核心是pandas的int64(numpy类型)不是Python原生整数类型,而JSON序列化只支持Python原生数据类型,导致API请求失败。另外你的batchUpdate请求体格式也有问题,得一起修正。
第一步:把pandas数据转换为Python原生类型
你可以写一个通用的转换函数,把numpy的数值类型转成原生类型,同时保留其他类型(比如字符串)不变:
import numpy as np import pandas as pd def convert_to_native(val): # 处理numpy整数类型 if isinstance(val, np.integer): return int(val) # 处理numpy浮点数类型(如果你的DataFrame有float64也需要) elif isinstance(val, np.floating): return float(val) # 其他类型直接返回 else: return val
然后用这个函数转换你的DataFrame:
# 转换DataFrame的所有元素为原生类型 df_native = orders_compact.applymap(convert_to_native) # 生成包含表头和行数据的列表列表 values = [list(df_native.columns)] + df_native.values.tolist()
或者如果你不想写函数,也可以用更简洁的方式批量转换数值列:
# 把所有整数列转成Python原生int,浮点列转成原生float for col in orders_compact.select_dtypes(include=['int64']).columns: orders_compact[col] = orders_compact[col].astype(int) for col in orders_compact.select_dtypes(include=['float64']).columns: orders_compact[col] = orders_compact[col].astype(float) # 生成values列表 values = [list(orders_compact.columns)] + orders_compact.values.tolist()
第二步:修正batchUpdate请求体格式
你原来的data字段格式不符合API要求,Google Sheets API的batchUpdate要求data是一个字典列表,每个字典需要包含range(要写入的单元格范围)和values(你的数据)。比如:
batch_update_values_request_body = { 'value_input_option': 'USER_ENTERED', 'data': [ { # 指定要写入的范围,比如Sheet1的A1开始的区域,或者用动态范围 'range': 'Sheet1!A1', 'values': values } ] }
如果想更精准地指定范围(比如匹配数据的行列数),可以这样生成range:
# 假设工作表名为Sheet1 sheet_name = 'Sheet1' # 计算数据的列数(比如表头有N列,就到第N列) num_cols = len(orders_compact.columns) # 生成范围字符串,比如Sheet1!A1:X100(X对应列数,100对应行数) range_str = f'{sheet_name}!A1:{chr(65 + num_cols - 1)}{len(values)}' batch_update_values_request_body = { 'value_input_option': 'USER_ENTERED', 'data': [ { 'range': range_str, 'values': values } ] }
完整修正后的代码
把上面的步骤整合起来:
import numpy as np import pandas as pd # 1. 转换数据类型 def convert_to_native(val): if isinstance(val, np.integer): return int(val) elif isinstance(val, np.floating): return float(val) else: return val df_native = orders_compact.applymap(convert_to_native) values = [list(df_native.columns)] + df_native.values.tolist() # 2. 构建正确的请求体 sheet_name = 'Sheet1' num_cols = len(df_native.columns) range_str = f'{sheet_name}!A1:{chr(65 + num_cols - 1)}{len(values)}' batch_update_values_request_body = { 'value_input_option': 'USER_ENTERED', 'data': [ { 'range': range_str, 'values': values } ] } # 3. 发送请求 request = service.spreadsheets().values().batchUpdate(spreadsheetId=SPREADSHEET_ID, body=batch_update_values_request_body) response = request.execute()
为什么你之前的方法没生效?
- 用
astype的时候可能只处理了部分列,或者没有覆盖所有numpy数值类型(比如只转了int64但没转float64); to_json方法是把DataFrame转成JSON字符串,而API需要的是可序列化的Python对象,不是字符串,所以这个方法不适用。
内容的提问来源于stack exchange,提问作者Lai
相关产品推荐
相关产品推荐

