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使用cookielib库示例分享
Mar 03 Python
从零学Python之入门(三)序列
May 25 Python
Python连接mssql数据库编码问题解决方法
Jan 01 Python
利用Python绘制MySQL数据图实现数据可视化
Mar 30 Python
Python二分查找详解
Sep 13 Python
解决pycharm运行时interpreter为空的问题
Oct 29 Python
matlab中imadjust函数的作用及应用举例
Feb 27 Python
jupyter notebook中美观显示矩阵实例
Apr 17 Python
pycharm配置QtDesigner的超详细方法
Jan 25 Python
python 实现有道翻译功能
Feb 26 Python
浅谈pytorch中stack和cat的及to_tensor的坑
May 20 Python
Python实现数据的序列化操作详解
Jul 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脚本数据库功能详解(中)
2006/10/09 PHP
PHP基础学习小结
2011/04/17 PHP
php学习之运算符相关概念
2011/06/09 PHP
php空间不支持socket但支持curl时recaptcha的用法
2011/11/07 PHP
PHP实现的简单对称加密与解密方法实例小结
2017/08/28 PHP
FormValidate 表单验证功能代码更新并提供下载
2008/08/23 Javascript
jquery ajax 同步异步的执行示例代码
2010/06/23 Javascript
js跨域问题之跨域iframe自适应大小实现代码
2010/07/17 Javascript
基于jQuery的为attr添加id title等效果的实现代码
2011/04/20 Javascript
JS基础之undefined与null的区别分析
2011/08/08 Javascript
javascript中onmouse事件在div中失效问题的解决方法
2012/01/09 Javascript
用js将内容复制到剪贴板兼容浏览器
2014/03/18 Javascript
JavaScript实现点击单选按钮改变输入框中文本域内容的方法
2015/08/12 Javascript
js支持键盘控制的左右切换立体式图片轮播效果代码分享
2015/08/26 Javascript
JQuery实现左右滚动菜单特效
2015/09/28 Javascript
深入解析JavaScript编程中的this关键字使用
2015/11/09 Javascript
JavaScript操作选择对象的简单实例
2016/05/16 Javascript
浅谈jQuery before和insertBefore的区别
2016/12/04 Javascript
Angular 2父子组件数据传递之@Input和@Output详解(下)
2017/07/05 Javascript
vue Element-ui input 远程搜索与修改建议显示模版的示例代码
2017/10/19 Javascript
vue项目从node8.x升级到12.x后的问题解决
2019/10/25 Javascript
详解Vue的mixin策略
2020/11/19 Vue.js
零基础写python爬虫之爬虫框架Scrapy安装配置
2014/11/06 Python
python正则表达式的使用
2017/06/12 Python
Python2包含中文报错的解决方法
2018/07/09 Python
在Python中将函数作为另一个函数的参数传入并调用的方法
2019/01/22 Python
Python中那些 Pythonic的写法详解
2019/07/02 Python
pytorch 输出中间层特征的实例
2019/08/17 Python
Pytorch Tensor的统计属性实例讲解
2019/12/30 Python
video下autoplay属性无效的解决方法(添加muted属性)
2020/05/19 HTML / CSS
英国Office鞋店德国网站:在线购买鞋子、靴子和运动鞋
2018/12/19 全球购物
SQL Server的固定数据库角色都有哪些?对应的服务器权限有哪些?
2013/05/18 面试题
小学生暑假家长评语
2014/04/17 职场文书
求职信怎么写
2014/05/23 职场文书
维护民族团结演讲稿
2014/08/27 职场文书
创业计划之特色精品店
2019/08/12 职场文书