如何实现批量读取zip内CSV为与文件名同名的独立Pandas DataFrame
需要从zip压缩包中批量读取所有CSV文件,每个CSV对应生成独立的DataFrame,且DataFrame名称与对应CSV文件名保持一致,最终实现通过csvNameList中存储的文件名直接引用对应的DataFrame。当前已完成遍历zip包的基础逻辑,但卡在「将读取到的DataFrame绑定为与文件名同名的可调用变量」的环节。
现有问题代码如下:
import os import zipfile csvNameList = [] with zipfile.ZipFile('../data/999915.zip') as z: for filename in z.namelist(): csvNameList.append(filename.split(".")[1]) df_name = filename.split(".")[1] df_name = pd.read_csv(z.open(filename), header=None, sep='\|\|@@##', na_values='\\N')
现有代码没有建立「文件名-DataFrame」的绑定关系:代码中df_name = filename.split(".")[1]是把提取到的字符串赋值给了固定名称的df_name变量,后续的df_name = pd.read_csv(...)直接将该变量的值覆盖为DataFrame,全程没有生成和文件名同名的独立变量,自然无法通过文件名索引到对应的数据。
另外原代码缺少pandas导入逻辑,直接运行会报pd is not defined的错误。
方案1:字典映射(推荐)
无需创建零散的全局变量,不会造成命名空间污染,后续对DataFrame的遍历、查找、批量操作都更便捷,是Python中处理这类动态映射场景的标准写法。
示例代码:
import zipfile import pandas as pd csvNameList = [] # 初始化映射字典,存储 文件名标识 -> 对应DataFrame 的对应关系 df_container = {} with zipfile.ZipFile('../data/999915.zip') as z: for filename in z.namelist(): # 过滤非CSV格式的冗余文件,避免读取报错 if not filename.lower().endswith('.csv'): continue # 按照原逻辑提取文件名标识 file_key = filename.split(".")[1] csvNameList.append(file_key) # 读取CSV并存入映射容器 with z.open(filename) as f: df_container[file_key] = pd.read_csv( f, header=None, sep=r'\|\|@@##', na_values='\\N' )
使用方式:
- 所有可访问的文件名标识都存在
csvNameList中,和原有逻辑完全兼容 - 想获取某个文件名对应的DataFrame,直接从
df_container字典中按键取值即可,例如要读取标识为user_info的DataFrame,直接调用df_container['user_info']
方案2:动态绑定全局变量(不推荐)
如果确实需要实现「直接把文件名当变量名访问DataFrame」的效果,可以借助Python内置的globals()方法动态创建全局变量,但这种方式会直接把生成的变量写入全局命名空间,很容易和代码中已有的变量重名覆盖,排查问题的成本很高,仅在对场景有强需求时使用。
示例代码:
import zipfile import pandas as pd csvNameList = [] with zipfile.ZipFile('../data/999915.zip') as z: for filename in z.namelist(): if not filename.lower().endswith('.csv'): continue file_key = filename.split(".")[1] csvNameList.append(file_key) # 动态创建和文件名同名的全局变量,绑定读取到的DataFrame globals()[file_key] = pd.read_csv( z.open(filename), header=None, sep=r'\|\|@@##', na_values='\\N' )
使用效果:绑定完成后,直接输入和文件标识一致的变量名即可访问对应DataFrame,例如文件标识为trade_data,直接输入trade_data就能读取对应的数据。
- 读取zip内文件时,建议使用
with z.open(...)的上下文管理器写法,避免文件句柄泄漏 - 自定义的分隔符参数
sep建议添加r前缀转为原始字符串,避免特殊字符被Python转义导致分隔匹配失败 - 遍历zip内文件时务必添加后缀判断,过滤系统自动生成的隐藏文件(如macOS的
.DS_Store)、文件夹项等非CSV内容,避免触发读取异常 - 文件名标识的提取逻辑可以根据实际文件结构调整,例如文件路径带文件夹层级时,可先提取纯文件名部分再拆分标识
内容的提问来源于stack exchange,提问作者cyrus24

