我对Python相当陌生,我试图将一个文本文件中的条目由两行组成,并将其拆分为一批max。400件物品。
我正在处理的数据是数以千计的FASTA格式的序列(带标题的纯文本,用于生物信息学),其中的条目看起来像这样:
HORVU6Hr1G000325.5
PIPPPASHFHPHHQNPSAATQPLCAAMAPAAKKPPLKSSSSHNSAAGDAA
HORVU6Hr1G000326.1
MVKFTAEELRGIMDKKNNIRNMSVIAHVD
...
在Biopython中,有一个解析器SeqIO.parse,它允许将这些作为由ID和字符串组成的对象数组进行访问,我需要在代码的后面部分使用这些对象,因为我需要节省内存,所以我希望避免阅读/解析源文件的次数超过必要的次数。
在Biopython手册中,有一种推荐的方法可以通过生成器来实现这一点,我正在使用:https://biopython.org/wiki/Split_large_file
然而,我使用的是Python 3.7,而代码是Python 2.x,所以肯定有一些必要的更改。我已经改变了
entry = iterator.next()
进入
entry = next(iterator)
但我不确定这是不是我需要改变的全部
代码如下:
def batch_iterator(iterator, batch_size=400):
"""Returns lists of length batch_size."""
entry = True # Make sure we loop once
while entry:
batch = []
while len(batch) < batch_size:
try:
entry = next(iterator)
except StopIteration:
entry = None
if entry is None:
# End of file
break
batch.append(entry)
if batch:
yield batch
while True:
bsequence = input("Please enter the full path to your FASTA file(e.g. c:\\folder1\\folder2\\protein.fasta):\n")
try:
fastafile = open(bsequence)
break
except:
print("File not found!\n")
record_iter = SeqIO.parse(fastafile,"fasta")
num = 0
for line in fastafile:
if line.startswith(">"):
num += 1
print("num=%i" % (num,))
if num > 400:
print("The specified file contains %i sequences. It's recommended to split the FASTA file into batches of max. 400 sequences.\n" % (num,))
while True:
decision = input("Do you wish to create batch files? (Original file will not be overwritten)\n(Y/N):")
if (decision == 'Y' or 'y'):
for i, batch in enumerate(batch_iterator(record_iter, 400), 1):
filename = "group_%i.fasta" % (i + 1)
with open(filename, "w") as handle:
count = SeqIO.write(batch, handle, "fasta")
print("Wrote %i records to %s" % (count, filename))
break
elif (decision == 'N' or 'n'):
break
else:
print('Invalid input\n')
...next part of the code
当我运行这个程序时,在Y/N提示符之后,即使我键入Y,程序也会跳到代码的下一部分,而不会创建任何新文件。调试器显示以下内容:
Do you wish to create batch files? (Original file will not be overwritten)
(Y/N):Y
Traceback (most recent call last):
File "\Biopython\mainscript.py", line 32, in batch_iterator
entry = next(iterator)
StopIteration
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1569, in _trace
return self._trace_and_catch(frame, event, arg)
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1611, in _trace_and_catch
frame.f_back, event, marker_function_args, node
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1656, in _handle_progress_event
self._save_current_state(frame, event, args, node)
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1738, in _save_current_state
exception_info = self._export_exception_info()
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1371, in _export_exception_info
"affected_frame_ids": exc[1]._affected_frame_ids_,
AttributeError: 'StopIteration' object has no attribute '_affected_frame_ids_'
Python 2.x和Python 3.x之间有什么我忽略的区别吗?问题出在别的地方吗?这种做法是否完全错误?先谢谢你了!
1条答案
按热度按时间jdzmm42g1#
我不能检查你的整个代码,因为你已经省略了它的一部分,但我可以看到两个错误的事情在这里:
这些行正在耗尽文件对象
fastafile
。完全删除这些行(并记住修复下面的缩进,删除if num > 400:
检查等)。这不是你想的那样将其更改为
if decision in ('Y', 'y'):
或if decision.lower() == 'y':
。在下面的if (decision == 'N' or 'n'):
行中重复这个模式,所以也要修改它。进行更改并尝试再次运行代码。
说明
第1期:在Python中,文件对象(即
open('filename.txt', 'r')
返回的)是一个生成器,这意味着它只能迭代一次。这可能看起来有点奇怪,但这就是使用生成器的全部意义。作为文件对象的生成器允许文件逐行循环,而不必一次加载整个文件内容-生成器只需跟踪下一行。另一方面,它们不能倒退,所以当你写
for line in fastafile
块时,你耗尽了生成器。当您稍后尝试调用batch_iterator(record_iter, 400)
时,record_iter
中的生成器已经耗尽,这就是为什么您稍后会遇到错误-如果没有任何东西可以解析,则batch_iterator
无法解析fasta序列。第2期:对于带有布尔运算符的条件,例如
if (decision == 'Y' or 'y'):
,Python总是分别计算两边。所以Python实际上看到的是if (bool(decision == 'Y') or bool('y')):
。由于
bool('y')
的计算结果为True
(就像任何非空字符串一样),因此表达式变为if (bool(decision == 'Y') or True):
,这显然总是为真。使用我建议的方法之一,以便将变量与条件中的多个值进行比较。