如何将FTP服务器上的.xlsx字节流转为pandas DataFrame?
解决FTP读取.xlsx字节流到pandas DataFrame的问题
你的问题核心出在FTP分块数据的处理逻辑:ftp.retrbinary会分多次调用回调函数,每次传入一小段文件字节,但你定义的BinaryReader.__call__方法每次都用新的BytesIO(s)覆盖原有数据,最终myBinary.data里只有最后一块字节(文件不完整),同时未将BytesIO的读写指针重置到开头,导致openpyxl读取时出现定位错误。
修复方案1:修正回调逻辑,累加分块数据
调整BinaryReader类,在回调中把每次收到的字节追加到同一个BytesIO对象中:
from ftplib import FTP import pandas as pd from io import BytesIO # 建立FTP连接 ftp = FTP() ftp.connect(host='myhost', port=myport) ftp.login(user='myuser', passwd='mypassword') class BinaryReader: def __init__(self): self.data = BytesIO() def __call__(self, s): # 追加字节,而非覆盖原有数据 self.data.write(s) myBinary = BinaryReader() folder = 'myFolder/' file = 'myFile.xlsx' ftp.retrbinary(f'RETR {folder}{file}', myBinary) # 重置指针到文件开头,否则pandas会从末尾开始读取 myBinary.data.seek(0) # 读取为DataFrame df = pd.read_excel(myBinary.data, engine='openpyxl') # 关闭FTP连接 ftp.quit()
修复方案2:更简洁的写法(无需自定义类)
直接用BytesIO的write方法作为回调函数,省去自定义类的步骤:
from ftplib import FTP import pandas as pd from io import BytesIO ftp = FTP() ftp.connect(host='myhost', port=myport) ftp.login(user='myuser', passwd='mypassword') file_data = BytesIO() ftp.retrbinary(f'RETR myFolder/myFile.xlsx', file_data.write) # 重置指针到开头 file_data.seek(0) df = pd.read_excel(file_data, engine='openpyxl') ftp.quit()
关键注意点
- 确保容器中已安装
openpyxl:在requirements.txt或Dockerfile中声明依赖,避免引擎缺失 - 确认FTP路径准确,避免末尾多斜杠或路径层级错误
- 处理完成后务必关闭FTP连接,避免资源泄漏
内容的提问来源于stack exchange,提问作者Daniposa
相关产品推荐
相关产品推荐

