使用Python ftplib从FTP读取CSV到Pandas DataFrame时遇文件不存在错误
解决方案
1. 修复pd.read_csv报错问题
你推测的没错,pd.read_csv()默认只能读取本地文件或公开可访问的URL,无法直接读取FTP服务器上的文件。需要先通过ftplib将文件内容拉取到内存中的文件对象(比如io.BytesIO),再传给pd.read_csv()。
修改后的代码示例:
import ftplib import pandas as pd from io import BytesIO def fetch_files(site, username, password, directory: str = '/', filematch: str = '*.csv'): with ftplib.FTP(site) as ftp: ftp.login(username, password) ftp.cwd(directory) list_ = [] for file_ in ftp.nlst(filematch): print(file_) # 创建内存文件对象接收FTP文件内容 file_data = BytesIO() # 用retrbinary获取二进制内容(CSV用二进制模式更稳妥) ftp.retrbinary(f'RETR {file_}', file_data.write) # 重置文件指针到开头,供pandas读取 file_data.seek(0) df = pd.read_csv(file_data, index_col=None, header=0) list_.append(df) return list_
注:原代码中重复创建ftp = ftplib.FTP(site)属于冗余操作,会覆盖with语句生成的FTP对象,直接删除即可。
2. 是否必须用ftp.retrlines?LIST和MLSD的区别
- 不是必须使用
retrlines,处理CSV文件更推荐用retrbinary:retrlines按行读取文本内容,适合纯日志类文本;retrbinary读取二进制流,能避免传输中因编码差异导致的乱码问题,通用性更强。 - LIST和MLSD是FTP获取文件列表的两种命令:
- LIST:传统列表命令,返回格式由FTP服务器决定,不同服务器输出样式可能不一致,需要手动解析内容,兼容性好但灵活性差。
- MLSD:标准化的机器可读列表命令,返回的每条记录包含文件名、大小、修改时间等结构化属性,无需手动解析,可靠性更高,但部分老旧FTP服务器可能不支持。
3. csv模块vs pandas:哪个更快?
如果仅需完成修改HTML转义字符、合并CSV文件这类简单操作,直接用Python内置csv模块更快——pandas加载整个DataFrame会带来额外的内存和性能开销,而csv模块逐行处理,轻量高效。
用csv模块处理的示例:
import ftplib import csv from io import StringIO import html def process_ftp_csv(site, username, password, directory='/', filematch='*.csv'): merged_rows = [] with ftplib.FTP(site) as ftp: ftp.login(username, password) ftp.cwd(directory) for file_ in ftp.nlst(filematch): print(file_) # 获取文件内容并转为字符串 file_data = StringIO() ftp.retrlines(f'RETR {file_}', file_data.write) file_data.seek(0) # 读取CSV并处理转义字符 reader = csv.DictReader(file_data) for row in reader: # 反转义HTML字符(比如&转为&) cleaned_row = {k: html.unescape(v) for k, v in row.items()} merged_rows.append(cleaned_row) # 可将merged_rows写入新CSV或直接用于SQL插入 return merged_rows
如果后续需要复杂的数据筛选、分析、转换操作,pandas的API会更便捷,综合效率更高。
内容的提问来源于stack exchange,提问作者NorrinRadd
相关产品推荐
相关产品推荐

