使用API上传Pandas DF至Google Sheets报错,转CSV再转回可解决
问题:Google Sheets API上传DataFrame时部分工作表报SSL EOF错误,转CSV后恢复
我通过Google Sheets API将网页抓取结果(存储在Pandas DataFrame)上传至同一份电子表格的多个工作表,大部分工作表正常,但有两个始终失败。移除try/except后得到ssl.SSLEOFError错误,而将DataFrame转存为CSV再重新读取后,就能成功上传。想知道原因,以及不用这个 workaround 的解决方案。
上传代码
def df_to_sheet(sheet, sheetName, df): try: df.replace(np.nan, '', inplace=True) df = df.T.reset_index().T.values.tolist() inputRange = sheetName + '!A1' response = sheet.values().update( spreadsheetId=sheets_conn.SPREADSHEET_ID, valueInputOption='RAW', range=inputRange, body=dict( majorDimension='ROWS', values=df ) ).execute() print(response) return True except: return False
报错信息
File "/usr/lib/python3/dist-packages/httplib2/__init__.py", line 1725, in request (response, content) = self._request( File "/usr/lib/python3/dist-packages/httplib2/__init__.py", line 1441, in _request (response, content) = self._conn_request(conn, request_uri, method, body, headers) File "/usr/lib/python3/dist-packages/httplib2/__init__.py", line 1364, in _conn_request conn.request(method, request_uri, body, headers) File "/usr/lib/python3.10/http/client.py", line 1282, in request self._send_request(method, url, body, headers, encode_chunked) File "/usr/lib/python3.10/http/client.py", line 1328, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "/usr/lib/python3.10/http/client.py", line 1277, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/usr/lib/python3.10/http/client.py", line 1076, in _send_output self.send(chunk) File "/usr/lib/python3.10/http/client.py", line 998, in send self.sock.sendall(data) File "/usr/lib/python3.10/ssl.py", line 1236, in sendall v = self.send(byte_view[count:]) File "/usr/lib/python3.10/ssl.py", line 1205, in send return self._sslobj.write(data) ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:2396)
临时解决方法(转CSV)
i = 0 if (df_to_sheet(sheet, sheetName, df)): print("Sheet Posted: ", sheetName) else: print("No Sheet Posted:", sheetName) df.to_csv(csv_path + str(i), index=False) df = pd.read_csv(csv_path + str(i)) if (df_to_sheet(sheet, sheetName, df)): print("Sheet Posted using workaround: ", sheetName) else: print("Still no Sheet Posted", sheetName) i += 1
原因分析
转CSV再读取的核心作用是清洗DataFrame中的特殊数据类型和隐藏格式问题:
- 网页抓取的DataFrame可能包含Pandas特殊数据类型(如带时区的
datetime64、category类型、NaT时间缺失值),这些类型直接转列表时,序列化过程会生成不符合API期望的格式,导致HTTP请求数据包异常,触发SSL连接中断。 - CSV是纯文本格式,写入再读取会强制将所有数据转换为字符串或基础数值类型,自动丢弃Pandas的元数据和特殊类型标记。
- 同时,这个过程会自动过滤网页抓取带来的非标准控制字符、编码异常字符,这类字符可能干扰API请求的数据包传输,引发SSL EOF错误。
无需CSV的解决方案
直接在原DataFrame上做针对性清洗:
- 统一数据类型:将非基础类型列转为字符串
import pandas as pd import numpy as np # 遍历列,把特殊数据类型转成字符串 for col in df.columns: if df[col].dtype not in ['int64', 'float64', 'object']: df[col] = df[col].astype(str)
- 清理特殊字符:移除控制字符和非标准空白符
import re # 对每个单元格清理非打印字符 df = df.applymap( lambda x: re.sub(r'[\x00-\x1F\x7F]', '', str(x)) if pd.notna(x) else '' )
- 替换所有特殊缺失值:覆盖
NaN之外的缺失标记
df = df.replace([pd.NA, pd.NaT, np.inf, -np.inf], '', regex=True)
- 优化DataFrame转列表的逻辑:避免
T.reset_index().T的复杂操作,直接用更简洁的方式保留表头和数据:
# 替换原代码中的df = df.T.reset_index().T.values.tolist() values = [df.columns.tolist()] + df.values.tolist()
内容的提问来源于stack exchange,提问作者Joey82
相关产品推荐
相关产品推荐

