将文件指针倒回上一行Python文件IO
我正在读一个大的基因文件的格式将文件指针倒回上一行Python文件IO,python,file-io,Python,File Io,我正在读一个大的基因文件的格式 >GeneID ACTCTCTCTATATATATATAT\n GCTCTGCTTCTAGAGAGAGTG\n TCTATTTGTTTATATATCTTT\n >GeneID GCTCTGCTTCTAGAAATTCCC\n ACTCTGTATATATTTTCAAAA\n GCTCTGCTTCTAGAGAGAGTG\n 每个基因都以一个>开始,然后是一个唯一的ID。之后是该基因的核苷酸序列。 不幸的是,该文件的生成使得序列的每一行之间都有换行符 我需要
>GeneID
ACTCTCTCTATATATATATAT\n
GCTCTGCTTCTAGAGAGAGTG\n
TCTATTTGTTTATATATCTTT\n
>GeneID
GCTCTGCTTCTAGAAATTCCC\n
ACTCTGTATATATTTTCAAAA\n
GCTCTGCTTCTAGAGAGAGTG\n
每个基因都以一个>开始,然后是一个唯一的ID。之后是该基因的核苷酸序列。
不幸的是,该文件的生成使得序列的每一行之间都有换行符
我需要将每个序列作为一个连续字符串读取。因此,我一直在使用下一种方法(如下所示)
我发现我的脚本只拾取了文件中的一半基因,因为当在导致while循环失败的条件下调用next时,文件指针指向下一个基因ID,然后当for循环的下一次迭代执行时,它移动到下一个文件
有没有办法将文件指针倒回上一行,这样我的for循环就可以将其作为一个新基因捕获
我看到过类似的问题,但没有一个是关于我阅读文件的具体方式
for line in file:
#do stuff
读取fasta文件有更简单的方法,例如:
entries = []
for line in filer:
if line.startswith('>'):
entries.append((line.rstrip()[1:], []))
else:
entries[-1][1].append(line.rstrip())
这将为您提供一个元组列表。第一个元素是序列ID,第二个元素是序列列表
在此之后很容易加入序列:
entries = [(x, "".join(y)) for x,y in entries]
读取fasta文件有更简单的方法,例如:
entries = []
for line in filer:
if line.startswith('>'):
entries.append((line.rstrip()[1:], []))
else:
entries[-1][1].append(line.rstrip())
这将为您提供一个元组列表。第一个元素是序列ID,第二个元素是序列列表
在此之后很容易加入序列:
entries = [(x, "".join(y)) for x,y in entries]
我会使用生成器,而不是跳过行(有些东西告诉我这可以大大简化): 现在,您只需几行代码就可以安全地迭代整个过程:
with open('file.txt', 'r') as handle:
for gene_id, nucleotides in parse_file(handle):
print gene_id, nucleotides
还有
或使用itertools
的更通用功能:
def grouper(line):
return line.startswith('>') and line[1:]
def itersplit(it, pred):
groups = (list(group) for key, group in itertools.groupby(it, pred))
yield from zip(groups, groups)
def parse(file):
for key, group in itersplit(file, grouper):
yield key[0], ''.join(group)
我会使用生成器,而不是跳过行(有些东西告诉我这可以大大简化): 现在,您只需几行代码就可以安全地迭代整个过程:
with open('file.txt', 'r') as handle:
for gene_id, nucleotides in parse_file(handle):
print gene_id, nucleotides
还有
或使用itertools
的更通用功能:
def grouper(line):
return line.startswith('>') and line[1:]
def itersplit(it, pred):
groups = (list(group) for key, group in itertools.groupby(it, pred))
yield from zip(groups, groups)
def parse(file):
for key, group in itersplit(file, grouper):
yield key[0], ''.join(group)
有没有办法将文件指针倒回上一行,这样我的for循环就可以将其作为一个新基因捕获
在Python3中,不能。不能将文件迭代与文件指针上的显式操作混合使用
也许在Python 2中。但这只是偶然发生的,这就是为什么它在3.0中被禁止的原因,而且它不能保证在任何情况下都能正常工作。所以,你不应该这么做
更好的方法是询问如何倒带迭代器。答案是。您可以使用tee
向前窥视。您可以将迭代器重新绑定到链([推后值],迭代器)
。等等
但是,正如其他人所指出的,有一种更好的方法可以做到这一点。你真的不需要向前看或向后看,你只需要把事情分组。您也可以使用itertools
来实现这一点,但在本例中,它非常简单,您不妨直接实现它,正如Blender所示
有没有办法将文件指针倒回上一行,这样我的for循环就可以将其作为一个新基因捕获
在Python3中,不能。不能将文件迭代与文件指针上的显式操作混合使用
也许在Python 2中。但这只是偶然发生的,这就是为什么它在3.0中被禁止的原因,而且它不能保证在任何情况下都能正常工作。所以,你不应该这么做
更好的方法是询问如何倒带迭代器。答案是。您可以使用tee
向前窥视。您可以将迭代器重新绑定到链([推后值],迭代器)
。等等
但是,正如其他人所指出的,有一种更好的方法可以做到这一点。你真的不需要向前看或向后看,你只需要把事情分组。您也可以使用
itertools
来实现这一点,但在本例中,它非常简单,您不妨直接实现它,正如Blender所示。这里有另一个使用re
和mmap
的方法:
import mmap, re
with open(your_file) as fin:
mm = mmap.mmap(fin.fileno(), 0, access=mmap.ACCESS_READ)
for match in re.finditer('>([^\n]+)([^>]*)', mm, flags=re.DOTALL):
print match.group(1), match.group(2).replace('\n', '')
#GeneID1 ACTCTCTCTATATATATATATGCTCTGCTTCTAGAGAGAGTGTCTATTTGTTTATATATCTTT
#GeneID2 GCTCTGCTTCTAGAAATTCCCACTCTGTATATATTTTCAAAAGCTCTGCTTCTAGAGAGAGTG
这样做可以将整个文件视为一个字符串,但会利用操作系统按需提供文件的一部分来完成正则表达式。由于它使用了
finditer
,我们也没有在内存中建立结果集。这里有另一个使用re
和mmap
的方法:
import mmap, re
with open(your_file) as fin:
mm = mmap.mmap(fin.fileno(), 0, access=mmap.ACCESS_READ)
for match in re.finditer('>([^\n]+)([^>]*)', mm, flags=re.DOTALL):
print match.group(1), match.group(2).replace('\n', '')
#GeneID1 ACTCTCTCTATATATATATATGCTCTGCTTCTAGAGAGAGTGTCTATTTGTTTATATATCTTT
#GeneID2 GCTCTGCTTCTAGAAATTCCCACTCTGTATATATTTTCAAAAGCTCTGCTTCTAGAGAGAGTG
这样做可以将整个文件视为一个字符串,但会利用操作系统按需提供文件的一部分来完成正则表达式。由于它使用了
finditer
,我们也没有在内存中建立结果集。这不会错过最后一个条目吗?由于文件不是以>
?@Blender开头的行结束的:首先将行上的迭代器分组为批上的迭代器,其中以'>'
开头的行标记一个新的批,然后只处理每个批,显然可以简化文件。但我认为,对于新手来说,生成的代码可能更难理解,因此您已经编写的代码是说明这一想法的完美方式。@Blender:我将编写一个更通用的itersplit
函数,它接受一个谓词和一个迭代器,每次谓词为真时,组上的迭代器都会被拆分。另外,我认为使用takewhile
比使用groupby
更简单。不过,我还是觉得你原来的版本更清晰了。@Blender:事实上,没关系;轻松使用takewhile
需要在其next
周围使用两个参数iter
,这太傻了。但是你对groupby
所做的只是(a)扔掉键,(b)列出值,以及(c)将值分组成对(因为键总是交替的),所以……这几乎是一个1行。请参阅我对您答案的编辑。@abarnert,只要在使用的Python版本中允许从中获得收益。。。但是是的-比我的mmap
和re
方法好得多这不会错过最后一个条目吗?因为文件没有结束