问题描述
我写这个是为了检索蛋白质登录号列表 (acc_list.txt) 的 FASTA 序列,每个都在一个新行上,并将它们写入一个 txt 文件 (prot_list)。
x=0
with open("acc_list.txt","r") as input:
number = sum(1 for items in input) ###
with open("acc_list.txt","r") as input:
with open ("prot_list.txt","w") as output:
for acc in input:
handle = Entrez.efetch(db="protein",id=acc,rettype="fasta")
x+=1
print("Dealing with",str(acc.strip()),str(x),"out of",str(number),sep=" ")
output.write(handle.read())
这是一个很大的列表,所以倒数第二行让我了解进度。
如您所见,number = sum(1 for items in input)
给出了总行数,但我必须单独打开和关闭文件,因为如果我将其放在后一个 with
语句下,即
x=0
with open("acc_list.txt","w") as output:
for acc in input:
number = sum(1 for items in input) ###
handle = Entrez.efetch(db="protein",sep=" ")
output.write(handle.read())
它在对物品进行计数后停止并且不提供其他输出。
我猜这是因为 number = sum(1 for items in input)
遍历文件并结束迭代。
我很好奇是否有更有效的方法来获取文件中的行数?我可以想象,如果我使用更大的列表,我的方法可能会出现问题。我看过较旧的答案,它们都涉及首先遍历文件。
解决方法
从这里复制Is there a way to shallow copy an existing file-object ?
我已经结束了:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 7 11:40:04 2021
@author: Pietro
https://stackoverflow.com/questions/67850117/more-streamline-way-to-count-lines-in-file-python
"""
from Bio import Entrez
from itertools import tee
x=0
with open("acc_list.txt","r") as input:
with open ("prot_list.txt","w") as output:
input1,input2 = tee(input,2)
number = sum(1 for items in input2)-1
print(number)
for acc in input1:
if acc.strip() != '':
try:
handle = Entrez.efetch(db="protein",id=acc,rettype="fasta")
x+=1
print("Dealing with",str(acc.strip()),str(x),"out of",str(number),sep=" ")
output.write(handle.read())
except:
pass
不确定是更快还是您要找的,请告诉我们。
此外,我注意到在我的 acc_list.txt 文件的末尾,我总是将文件末尾的空行作为一个空的登录号,所以有点像 找到了一个巧妙的方法来抑制它
,您可以让 grep
之类的现有工具来完成这项工作:
import subprocess
p = subprocess.run(['grep','-c','>','acc_list.txt'],check=True,capture_output=True,text=True)
seq_count = int(p.stdout)
在我的测试中,这比在 Python 中打开和计数要快,尤其是对于较大的文件。当最后一行不包含 >
时,计数 \n
而不是换行符也可以避免出现问题。