编程语言
首页 > 编程语言> > Python 3.x-如何有效地将对象数组拆分为较小的批处理文件?

Python 3.x-如何有效地将对象数组拆分为较小的批处理文件?

作者:互联网

我对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和3.x之间有什么区别吗?问题在其他地方吗?这种方法完全错误吗?提前致谢!

解决方法:

由于您省略了一部分代码,因此我无法检查整个代码,但在这里我会看到两处错误的内容:

num = 0
for line in fastafile:
    if line.startswith(">"):
        num += 1

这些行耗尽了您的文件对象fastafile.完全删除这些行(并记住要修复下面的缩进,如果num> 400:请取消,等等).

if (decision == 'Y' or 'y'):

这并没有按照您的想法做.将其更改为if决策(‘Y’,’y’):或if Decision.lower()==’y’:.您在下面的if(decision ==’N’或’n’):行中重复此模式,因此也进行更改.

进行更改,然后尝试再次运行代码.

说明

第一个问题:在Python中,文件对象(即open(‘filename.txt’,’r’)返回的内容)是一个生成器,这意味着它只能被迭代一次.乍一看这似乎有些怪异,但这就是使用生成器的全部意义所在.生成器作为文件对象允许文件逐行循环,而不必一次加载整个文件内容-生成器仅跟踪下一行.

缺点是它们不能向后移动,因此当您在fastafile块中编写for行时,将耗尽生成器.当您稍后尝试调用batch_iterator(record_iter,400)时,record_iter中的生成器已经用尽,这就是为什么您以后会遇到错误的原因-如果没有任何要解析的内容,batch_iterator无法解析fasta序列.

第二个问题:对于带有布尔运算符的条件,例如if(decision ==’Y’或’y’):, Python将始终分别评估双方.因此,Python实际上会查看(bool(decision ==’Y’)还是bool(‘y’)):.

由于bool(‘y’)的计算结果为True(就像任何非空字符串一样),因此您的表达式变为if(bool(decision ==’Y’)或True):,这显然总是对的.

使用我建议的一种方法,以便将变量与条件中的多个值进行比较.

标签:biopython,next,python-3-x,generator,python
来源: https://codeday.me/bug/20191210/2104956.html