Python用list或dict字段模式读取文件的方法


Posted in Python onJanuary 10, 2017

前言

Python用于处理文本数据绝对是个利器,极为简单的读取、分割、过滤、转换支持,使得开发者不需要考虑繁杂的流文件处理过程(相对于JAVA来说的,嘻嘻)。博主自己工作中,一些复杂的文本数据处理计算,包括在HADOOP上编写Streaming程序,均是用Python完成。

而在文本处理的过程中,将文件加载内存中是第一步,这就涉及到怎样将文件中的某一列映射到具体的变量的过程,最最愚笨的方法,就是按照字段的下标进行引用,比如这样子:

# fields是读取了一行,并且按照分隔符分割之后的列表
user_id = fields[0]
user_name = fields[1]
user_type = fields[2]

如果按照这种方式读取,一旦文件有顺序、增减列的变动,代码的维护是个噩梦,这种代码一定要杜绝。

本文推荐两种优雅的方式来读取数据,都是先配置字段模式,然后按照模式读取,而模式则有字典模式和列表模式两种形式;

读取文件,按照分隔符分割成字段数据列表

首先读取文件,按照分隔符分割每一行的数据,返回字段列表,以便后续处理。

代码如下:

def read_file_data(filepath):
 '''根据路径按行读取文件, 参数filepath:文件的绝对路径
 @param filepath: 读取文件的路径
 @return: 按\t分割后的每行的数据列表
 '''
 fin = open(filepath, 'r')
 for line in fin:
  try:
   line = line[:-1]
   if not line: continue
  except:
   continue
  
  try:
   fields = line.split("\t")
  except:
   continue
  # 抛出当前行的分割列表
  yield fields
 fin.close()

使用yield关键字,每次抛出单个行的分割数据,这样在调度程序中可以用for fields in read_file_data(fpath)的方式读取每一行。

映射到模型之方法1:使用配置好的字典模式,装配读取的数据列表

这种方法配置一个{“字段名”: 字段位置}的字典作为数据模式,然后按照该模式装配读取的列表数据,最后实现用字典的方式访问数据。

所使用的函数:

@staticmethod
def map_fields_dict_schema(fields, dict_schema):
 """根据字段的模式,返回模式和数据值的对应值;例如 fields为['a','b','c'],schema为{'name':0, 'age':1},那么就返回{'name':'a','age':'b'}
 @param fields: 包含有数据的数组,一般是通过对一个Line String通过按照\t分割得到
 @param dict_schema: 一个词典,key是字段名称,value是字段的位置;
 @return: 词典,key是字段名称,value是字段值
 """
 pdict = {}
 for fstr, findex in dict_schema.iteritems():
  pdict[fstr] = str(fields[int(findex)])
 return pdict

有了该方法和之前的方法,可以用以下的方式读取数据:

# coding:utf8
"""
@author: www.crazyant.net
测试使用字典模式加载数据列表
优点:对于多列文件,只通过配置需要读取的字段,就能读取对应列的数据
缺点:如果字段较多,每个字段的位置配置,较为麻烦
"""
import file_util
import pprint
 
# 配置好的要读取的字典模式,可以只配置自己关心的列的位置
dict_schema = {"userid":0, "username":1, "usertype":2}
for fields in file_util.FileUtil.read_file_data("userfile.txt"):
 # 将字段列表,按照字典模式进行映射
 dict_fields = file_util.FileUtil.map_fields_dict_schema(fields, dict_schema)
 pprint.pprint(dict_fields)

输出结果:

{'userid': '1', 'username': 'name1', 'usertype': '0'}
{'userid': '2', 'username': 'name2', 'usertype': '1'}
{'userid': '3', 'username': 'name3', 'usertype': '2'}
{'userid': '4', 'username': 'name4', 'usertype': '3'}
{'userid': '5', 'username': 'name5', 'usertype': '4'}
{'userid': '6', 'username': 'name6', 'usertype': '5'}
{'userid': '7', 'username': 'name7', 'usertype': '6'}
{'userid': '8', 'username': 'name8', 'usertype': '7'}
{'userid': '9', 'username': 'name9', 'usertype': '8'}
{'userid': '10', 'username': 'name10', 'usertype': '9'}
{'userid': '11', 'username': 'name11', 'usertype': '10'}
{'userid': '12', 'username': 'name12', 'usertype': '11'}

映射到模型之方法2:使用配置好的列表模式,装配读取的数据列表

如果需要读取文件所有列,或者前面的一些列,那么配置字典模式优点复杂,因为需要给每个字段配置索引位置,并且这些位置是从0开始完后数的,属于低级劳动,需要消灭。

列表模式应命运而生,先将配置好的列表模式转换成字典模式,然后按字典加载就可以实现。

转换模式,以及用按列表模式读取的代码:

@staticmethod
def transform_list_to_dict(para_list):
 """把['a', 'b']转换成{'a':0, 'b':1}的形式
 @param para_list: 列表,里面是每个列对应的字段名
 @return: 字典,里面是字段名和位置的映射
 """
 res_dict = {}
 idx = 0
 while idx < len(para_list):
  res_dict[str(para_list[idx]).strip()] = idx
  idx += 1
 return res_dict
 
@staticmethod
def map_fields_list_schema(fields, list_schema):
 """根据字段的模式,返回模式和数据值的对应值;例如 fields为['a','b','c'],schema为{'name', 'age'},那么就返回{'name':'a','age':'b'}
 @param fields: 包含有数据的数组,一般是通过对一个Line String通过按照\t分割得到
 @param list_schema: 列名称的列表list
 @return: 词典,key是字段名称,value是字段值
 """
 dict_schema = FileUtil.transform_list_to_dict(list_schema)
 return FileUtil.map_fields_dict_schema(fields, dict_schema)

使用的时候,可以用列表的形式配置模式,不需要配置索引更加简洁:

# coding:utf8
"""
@author: www.crazyant.net
测试使用列表模式加载数据列表
优点:如果读取所有列,用列表模式只需要按顺序写出各个列的字段名就可以
缺点:不能够只读取关心的字段,需要全部读取
"""
import file_util
import pprint
 
# 配置好的要读取的列表模式,只能配置前面的列,或者所有咧
list_schema = ["userid", "username", "usertype"]
for fields in file_util.FileUtil.read_file_data("userfile.txt"):
 # 将字段列表,按照字典模式进行映射
 dict_fields = file_util.FileUtil.map_fields_list_schema(fields, list_schema)
 pprint.pprint(dict_fields)

运行结果和字典模式的完全一样。

file_util.py全部代码

以下是file_util.py中的全部代码,可以放在自己的公用类库中使用

# -*- encoding:utf8 -*-
'''
@author: www.crazyant.net
@version: 2014-12-5
'''
 
class FileUtil(object):
 '''文件、路径常用操作方法
 '''
 @staticmethod
 def read_file_data(filepath):
  '''根据路径按行读取文件, 参数filepath:文件的绝对路径
  @param filepath: 读取文件的路径
  @return: 按\t分割后的每行的数据列表
  '''
  fin = open(filepath, 'r')
  for line in fin:
   try:
    line = line[:-1]
    if not line: continue
   except:
    continue
   
   try:
    fields = line.split("\t")
   except:
    continue
   # 抛出当前行的分割列表
   yield fields
  fin.close()
 
 @staticmethod
 def transform_list_to_dict(para_list):
  """把['a', 'b']转换成{'a':0, 'b':1}的形式
  @param para_list: 列表,里面是每个列对应的字段名
  @return: 字典,里面是字段名和位置的映射
  """
  res_dict = {}
  idx = 0
  while idx < len(para_list):
   res_dict[str(para_list[idx]).strip()] = idx
   idx += 1
  return res_dict
 
 @staticmethod
 def map_fields_list_schema(fields, list_schema):
  """根据字段的模式,返回模式和数据值的对应值;例如 fields为['a','b','c'],schema为{'name', 'age'},那么就返回{'name':'a','age':'b'}
  @param fields: 包含有数据的数组,一般是通过对一个Line String通过按照\t分割得到
  @param list_schema: 列名称的列表list
  @return: 词典,key是字段名称,value是字段值
  """
  dict_schema = FileUtil.transform_list_to_dict(list_schema)
  return FileUtil.map_fields_dict_schema(fields, dict_schema)
 
@staticmethod
def map_fields_dict_schema(fields, dict_schema):
 """根据字段的模式,返回模式和数据值的对应值;例如 fields为['a','b','c'],schema为{'name':0, 'age':1},那么就返回{'name':'a','age':'b'}
 @param fields: 包含有数据的数组,一般是通过对一个Line String通过按照\t分割得到
 @param dict_schema: 一个词典,key是字段名称,value是字段的位置;
 @return: 词典,key是字段名称,value是字段值
 """
 pdict = {}
 for fstr, findex in dict_schema.iteritems():
  pdict[fstr] = str(fields[int(findex)])
 return pdict

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用python能有一定的帮助,如果有疑问大家可以留言交流。

Python 相关文章推荐
用Python的线程来解决生产者消费问题的示例
Apr 02 Python
Python中的多重装饰器
Apr 11 Python
用实例解释Python中的继承和多态的概念
Apr 27 Python
python访问类中docstring注释的实现方法
May 04 Python
Python2.7下安装Scrapy框架步骤教程
Dec 22 Python
Python实现批量执行同目录下的py文件方法
Jan 11 Python
浅谈Python 多进程默认不能共享全局变量的问题
Jan 11 Python
python实现集中式的病毒扫描功能详解
Jul 09 Python
python3.7 的新特性详解
Jul 25 Python
基于Python新建用户并产生随机密码过程解析
Oct 08 Python
opencv python 对指针仪表读数识别的两种方式
Jan 14 Python
Python字典和列表性能之间的比较
Jun 07 Python
python导入时小括号大作用
Jan 10 #Python
python实现应用程序在右键菜单中添加打开方式功能
Jan 09 #Python
ubuntu系统下 python链接mysql数据库的方法
Jan 09 #Python
利用Python中unittest实现简单的单元测试实例详解
Jan 09 #Python
Python中的sort()方法使用基础教程
Jan 08 #Python
Python守护进程和脚本单例运行详解
Jan 06 #Python
Python 基础知识之字符串处理
Jan 06 #Python
You might like
php检查字符串中是否包含7位GSM字符的方法
2015/03/17 PHP
php计算到指定日期还有多少天的方法
2015/04/14 PHP
php pdo连接数据库操作示例
2019/11/18 PHP
JS判断不同分辨率调用不同的CSS样式文件实现思路及测试代码
2013/01/23 Javascript
JavaScript闭包函数访问外部变量的方法
2014/08/27 Javascript
js实现window.open不被拦截的解决方法汇总
2014/10/30 Javascript
js控制div弹出层实现方法
2015/05/11 Javascript
js实现文本框宽度自适应文本宽度的方法
2015/08/13 Javascript
jQuery+PHP星级评分实现方法
2015/10/02 Javascript
js简单倒计时实现代码
2016/04/30 Javascript
jQuery使用siblings获取某元素所有同辈(兄弟姐妹)元素用法示例
2017/01/30 Javascript
Javascript调试之console对象——你不知道的一些小技巧
2017/07/10 Javascript
vue 父组件调用子组件方法及事件
2018/03/29 Javascript
Angular入口组件(entry component)与声明式组件的区别详解
2018/04/09 Javascript
jQuery实现DIV响应鼠标滑过由下向上展开效果示例【测试可用】
2018/04/26 jQuery
javascript中的offsetWidth、clientWidth、innerWidth及相关属性方法
2020/05/14 Javascript
Vue如何实现变量表达式选择器
2021/02/18 Vue.js
Python matplotlib绘图可视化知识点整理(小结)
2018/03/16 Python
详解pyenv下使用python matplotlib模块的问题解决
2018/11/29 Python
python random从集合中随机选择元素的方法
2019/01/23 Python
python适合人工智能的理由和优势
2019/06/28 Python
Python人工智能之路 jieba gensim 最好别分家之最简单的相似度实现
2019/08/13 Python
从训练好的tensorflow模型中打印训练变量实例
2020/01/20 Python
pytorch  网络参数 weight bias 初始化详解
2020/06/24 Python
css3中仿放大镜效果的几种方式原理解析
2020/12/03 HTML / CSS
销售人员工作自我评价
2014/09/21 职场文书
2015年党员创先争优承诺书
2015/01/22 职场文书
2015年女职工工作总结
2015/05/15 职场文书
感恩教育观后感
2015/06/17 职场文书
关于空气污染危害的感想
2015/08/11 职场文书
tensorflow学习笔记之tfrecord文件的生成与读取
2021/03/31 Python
Jupyter notebook 不自动弹出网页的解决方案
2021/05/21 Python
OpenCV-Python实现轮廓的特征值
2021/06/09 Python
springboot中一些比较常用的注解总结
2021/06/11 Java/Android
Redis 彻底禁用RDB持久化操作
2021/07/09 Redis
Oracle删除归档日志及添加定时任务
2022/06/28 Oracle