使用Python文件读写,自定义分隔符(custom delimiter)
众所周知,python文件读取文件的时候所支持的newlines(即换行符),是指定的。这一点不管是从python的doucuments上还是在python的源码中(作者是参考了python的io版本,并没有阅读C版本),都可以看出来:
if newline is not None and not isinstance(newline, str):
raise TypeError("illegal newline type: %r" % (type(newline),))
if newline not in (None, "", "n", "r", "rn"):
raise ValueError("illegal newline value: %r" % (newline,))
好吧,问题来了,如果你恰好是个苦逼的生物狗,正在用python处理所谓的fastq格式的测序结果文件,每次只读一行往往不是你想要的。Ok, 我们也都知道其实这个问题在Perl里面十分好解决,无非就是重新定义下文件的分割符($/,The input record separator, newline by default. Set undef to read through the end of file.)
local $/; # enable "slurp" mode
local $_ = <FH ; # whole file now here
s/n[ t]+/ /g;
简单粗暴有效!《Programming Perl》开头的那些关于什么是happiness定义看来所言非虚,所以你只要需要将$/定义为fastq格式的分隔符就ok了。
但是,如果是Python呢?(容易钻牛角尖的孩纸,又或者是不喜欢花括号的孩子…..反正就是强行高端了)。终于要进入正题了,OK,在python中又有两种方式解决这个问题,看你个人喜好选择了(当然要是有大神知道四种、五种方法,也不妨指导一下我这个小菜鸟)。
方案一的代码:
import _pyio
import io
import functools
class MyTextWrapper(_pyio.TextIOWrapper):
def readrecod(self, sep):
readnl, self._readnl = self._readnl, sep
self._readtranslate = False
self._readuniversal = False
try:
return self.readline()
finally:
self._readnl = readnl
#class MyTextWrapper(_pyio.TextIOWrapper):
# def __init__(self, *args, separator, **kwargs):
# super().__init__(*args,**kwargs)
# self._readnl = separator
# self._readtranslate = False
# self._readuniversal = False
# print("{}:t{}".format(self,self._readnl))
f = io.open('data',mode='rt')
#f = MyTextWrapper(f.detach(),separator = ' ')
#print(f._readnl)
f = MyTextWrapper(f.detach())
records=iter(functools.partial(f.readrecod, ' '), '')
for r in records:
print(r.strip(' '))
print("###")
Ok,这是Python3.x中的方法(亲测),那么在Python2.x中需要改动的地方,目测好像是(没有亲测)
super(MyTextWrapper,self).__init__(*args,**kwargs)
这个方法看上去还是比较elegant,但是efficient 吗?答案恐怕并不,毕竟放弃了C模块的速度优势,但是OOP写起来还是比较舒服的。对了值得指出的Python的I/O是一个layer一个layer的累加起来的。从这里我们就能看出来。当然里面的继承关系还是值得研究一下的,从最开始的IOBase一直到最后的TextIOWrapper,这里面的故事,还是要看一看的。
方案二的代码:
#!/usr/bin/env python
def delimited(file, delimiter = 'n', bufsize = 4096):
buf = ''
while True:
newbuf = file.read(bufsize)
if not newbuf:
yield buf
return
buf += newbuf
lines = buf.split(delimiter)
for line in lines[:-1]:
yield line
buf = lines[-1]
with open('data', 'rt') as f:
lines = delimited(f, ' ', bufsize = 1)
for line in lines:
print line,
print '######'
Ok,这里用到了所谓的generator函数,优雅程度也还行,至于效率么,请自行比较和测试吧(毕竟好多生物程序猿是不关心效率的…..)。如此一来,比Perl多敲了好多代码,唉,怀念Perl的时代啊,简单粗暴有效,就是幸福的哲学么。
当然还有童鞋要问,那么能不能又elegant还efficient(我可是一个高端的生物程序猿,我要强行高端!)答案是有的,请用Cython! 问题又来了,都Cython了,为什么不直接用C呢?确实,C语言优美又混乱。
补充知识:Python.json.常见两个错误处理(Expecting , delimiter)(Invalid control character at)
ValueError: Invalid control character at: line 1 column 122(char 123)
出现错误的原因是字符串中包含了回车符(r)或者换行符(n)
解决方案:
转义
json_data = json_data.replace(‘r’, ‘\r’).replace(‘n’, ‘\n’)
使用关键字strict
json.loads(json_data, strict=False)
ValueError: Expecting , delimiter: line 13 column 650 (char 4186)
原因:json数据不合法,类似“group_buy_create_description_text”: “1. Select the blue “Buy” button to let other shoppers buy with you.这样的内容出现在json数据中。
解决方案:
将类似的情形通过正则筛选出来通过下面的方式处理。
正则表达式如下:
json_data = json_data.replace(‘””‘, ‘”########”‘) js_str = ‘”[sS]+?”:s?”([sS]+?)”}?}?]?,’
后续使用中发现无法匹配value为空的情况,故先做一下预处理
这个正则可以匹配到大部分的key,value中的value值,但是也有例外,暂时的处理方法是如果匹配结果中包含”{“, “}”, “[“, “]”这样的字符,说明是匹配失败结果,跳过处理。其他的使用下边的方法替换掉可能出问题的字符。
如果大家有更好的正则匹配方式,欢迎随时批评指正。
def htmlEscape(input) {
if not input
return input;
input = input.replace("&", "&");
input = input.replace("<", "<");
input = input.replace(" ", ">");
input = input.replace(" ", " ");
input = input.replace("'", "'"); //IE暂不支持单引号的实体名称,而支持单引号的实体编号,故单引号转义成实体编号,其它字符转义成实体名称
input = input.replace(""", """); //双引号也需要转义,所以加一个斜线对其进行转义
input = input.replace("n", "<br/ "); //不能把n的过滤放在前面,因为还要对<和 过滤,这样就会导致<br/ 失效了
return input;
}
以上这篇使用Python文件读写,自定义分隔符(custom delimiter)就是小编分享给大家的全部内容了,希望能给大家一个参考。
- 使用redis构建可靠分布式锁
- 提高服务器程序性能的一些方法
- A+B for Matrices 及 C++ transform的用法
- socket读写返回值的处理
- 记录服务上线一年来的点点滴滴
- 实现两个N*N矩阵的乘法,矩阵由一维数组表示
- C++实现线程安全的单例模式
- 实现两个N*N矩阵的乘法,矩阵由一维数组表示
- 一步一步实现读写锁
- 二维数组的查找
- 从I/O复用谈epoll为什么高效
- C++ STL算法系列2---find ,find_first_of , find_if , adjacent_find的使用
- 2017企业安全技术热词有哪些?
- Raft协议实战之Redis Sentinel的选举Leader源码解析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 浙大版《C语言程序设计(第3版)》题目集 习题8-10 输出学生成绩
- 浙大版《C语言程序设计(第3版)》题目集 习题9-1 时间换算
- 浙大版《C语言程序设计(第3版)》题目集 习题9-3 平面向量加法
- 浙大版《C语言程序设计(第3版)》题目集 习题9-4 查找书籍
- 浙大版《C语言程序设计(第3版)》题目集 习题9-5 通讯录排序
- 浙大版《C语言程序设计(第3版)》题目集 习题7-5 找鞍点
- 浙大版《C语言程序设计(第3版)》题目集 练习5-1 求m到n之和
- 手把手教你用Python爬取快递100查询你的物流信息
- 浙大版《C语言程序设计(第3版)》题目集 练习5-2 找两个数中最大者
- 浙大版《C语言程序设计(第3版)》题目集 练习5-3 数字金字塔
- 浙大版《C语言程序设计(第3版)》题目集 习题5-1 符号函数
- 浙大版《C语言程序设计(第3版)》题目集 习题5-2 使用函数求奇数和
- 浙大版《C语言程序设计(第3版)》题目集 习题5-3 使用函数计算两点间的距离
- 浙大版《C语言程序设计(第3版)》题目集 习题5-4 使用函数求素数和
- Linux进程之如何查看进程详情?