• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

使用Python文件读写,自定义分隔符(custom delimiter)

python 搞代码 4年前 (2022-01-09) 21次浏览 已收录 0个评论

众所周知,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", "\r\n"):
 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/本文来源gaodai#ma#com搞*!代#%^码网5O是一个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的时代啊,简单粗暴有效,就是幸福的哲学么。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:使用Python文件读写,自定义分隔符(custom delimiter)

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址