在循环中打开和关闭文件

时间:2016-01-13 21:26:15

标签: python pandas biopython

假设我有一个包含数万个条目的列表,我想将它们写入文件。如果列表中的项目符合某些条件,我想关闭当前文件并启动一个新文件。

我遇到了一些问题,我认为这些问题源于我想根据该文件中的第一个条目命名文件。此外,启动新文件的信号取决于条目是否具有与前一个字段相同的字段。所以,例如想象我有这个列表:

l = [('name1', 10), ('name1', 30), ('name2', 5), ('name2', 7), ('name2', 3), ('name3', 10)]

我想最终得到3个文件,name1.txt应该包含1030name2.txt应该包含5,{{1} }和73应该有name3.txt。列表已经按第一个元素排序,所以我需要做的就是检查第一个元素是否与前一个元素相同,如果没有,则启动一个新文件。

起初我试过了:

10

据我所知,这有几个问题。首先,第一次通过循环,没有name = None for entry in l: if entry[0] != name: out_file.close() name = entry[0] out_file = open("{}.txt".format(name)) out_file.write("{}\n".format(entry[1])) else: out_file.write("{}\n".format(entry[1])) out_file.close() 关闭。其次,我无法关闭最后创建的out_file,因为它是在循环内定义的。以下解决了第一个问题,但似乎很笨:

out_file

有更好的方法吗?

而且,这似乎不应该解决关闭最后一个文件的问题,虽然这段代码运行正常 - 我是否误解了for entry in l: if name: if entry[0] != name: out_file.close() name = entry[0] out_file = open("{}.txt".format(name)) out_file.write("{}\n".format(entry[1])) else: out_file.write("{}\n".format(entry[1])) else: name = entry[0] out_file = open("{}.txt".format(name)) out_file.write("{}\n".format(entry[1])) out_file.close() 的范围?我认为它仅限于out_file循环内部。

编辑:我应该提到的,我的数据比这里指出的要复杂得多......它实际上并不在列表中,而是SeqRecord from BioPython

编辑2:好的,我以为我是在简化以避免分心。显然有相反的效果 - mea culpa 。以下是上面第二个代码块的等价物:

for

3 个答案:

答案 0 :(得分:4)

使用Python提供的工具更容易:

from itertools import groupby
from operator import itemgetter

items = [
    ('name1', 10), ('name1', 30),
    ('name2', 5), ('name2', 7), ('name2', 3),
    ('name3', 10)
]

for name, rows in groupby(items, itemgetter(0)):
    with open(name + ".txt", "w") as outf:
        outf.write("\n".join(str(row[1]) for row in rows))

编辑以匹配更新的问题,这是更新的解决方案; - )

for name, records in groupby(SeqIO.parse(some_genbank, 'gb'), lambda record:record.annotations['source']):
    with open(name + ".faa", "w+") as outf:
        for record in records:
            write_all_record(outf, record)

答案 1 :(得分:2)

如果您不介意使用pandas,可以按照以下方式处理:

import pandas as pd
df = pd.DataFrame(l)
df.columns = ['name', 'value']
df.groupby('name').apply(lambda x: x.to_csv('{}.txt'.format(x['name'].iloc[0]), index=False, header=False))

获取三个名为name1.txt的文本文件,如下所示:

name1,10
name1,30

答案 2 :(得分:1)

在不弄乱您的代码的情况下,为什么不在关闭之前检查out_file变量是否存在?

out_file=None
... #Some code
if out_file:
    out_file.close()

您也可以使用try/except

或者甚至可能会上课(虽然矫枉过正):

class f_temp():
    name = None
    def close(self):
        pass
out_file = f_temp()

for entry in l:
    if entry[0] != out_file.name:

...

现在再多阅读一下,为什么不按文件名对数据进行排序,然后只打开一个文件?

您也可以使用字典:

file_dict =dict()
for filename, value in l:
    if filename not in file_dict():
        file_dict[filename] = open("{}.txt".format(filename))
    file_dict[filename].write("{}\n".format(entry[1]))

for item in file_dict.items():
    item.close()