写入具有动态文件名的文件?

时间:2017-11-06 23:38:23

标签: python bigdata

我需要在DATE之前拆分一个大的txt文件(大约100GB, 10亿行)。该文件看起来像这样

ID*DATE*company
1111*201101*geico
1234*201402*travelers
3214*201003*statefarm
...

基本上有60个月,所以我应该得到60个子文件。我的Python脚本是

with open("myBigFile.txt") as f:
    for line in f: 
        claim = line.split("*")
        with open("DATE-"+str(claim[1])+".txt", "a") as fy:
            fy.write(claim[0]+"*"+claim[2]+"\n")

现在由于记录数量巨大,因此需要为每一行打开/关闭文件,因此运行速度太慢。所以我在考虑首先打开60个子文件,然后扫描文件,将每一行写入相应的子文件。 在扫描所有行之前,子文件不会关闭。但是,由于python会在删除引用时自动关闭文件(http://blog.lerner.co.il/dont-use-python-close-files-answer-depends/),所以我必须使用一些动态文件名,例如

claim[1].write(claim[0]+"*"+claim[2]+"\n")

请注意,您无法命名fyfy.write(claim[0]+"*"+claim[2]+"\n"),因为只要fy发生更改,它就会关闭文件。这可能在Python中吗?谢谢!

3 个答案:

答案 0 :(得分:0)

这样的事情怎么样:

with open("myBigFile.txt") as f:
subfiles = {}
for line in f: 
    claim = line.split("*")
    if not str(claim[1]) in subfiles:
        subfiles[str(claim[1])] = open("DATE-" + str(claim[1]) + ".txt", "a")
    subfile[str(claim[1])].write(claim[0]+"*"+claim[2]+"\n")

我相信这应该做到。

请注意,我目前没有限制在特定时刻打开的文件数量。要实现这一点,只需使用'len()'检查列表的大小,然后关闭所有文件或几个文件。

答案 1 :(得分:0)

您可以使用csv模块略微简化,并使用字典存储文件对象:

import csv

with open("myBigFile.txt") as big_file:
    reader = csv.reader(big_file, delimiter='*')
    subfiles = {}

    for id, date, company in reader:
        try:
            subfile = subfiles[date]
        except KeyError:
            subfile = open('DATE-{}.txt'.format(date), 'a')
            subfiles[date] = subfile

        subfile.write('{}*{}\n'.format(id, company))

    for subfile in subfiles.values():
        subfile.close()

答案 2 :(得分:0)

这是一个将文件句柄作为上下文管理器的一部分关闭的解决方案,与其他答案不同,这也会在发生错误时关闭子文件: - )

from contextlib import contextmanager

@contextmanager
def file_writer():
    fp = {}

    def write(line):
        id, date, company = line.split('*')
        outdata = "{}*{}\n".format(id, company)
        try:
            fp[date].write(outdata)
        except KeyError:
            fname = 'DATE-{}.txt'.format(date)
            fp[date] = open(fname, 'a')    # should it be a+?
            fp[date].write(outdata)

    yield write

    for f in fp.values():
        f.close()


def process():
    with open("myBigFile.txt") as f:
        with file_writer() as write:
            for i, line in enumerate(f):
                try:
                    write(line)
                except:
                    print('the error happened on line %d [%s]' % (i, line))

我不知道在单个处理器/磁​​盘上是否还有更多可以快速完成的工作。您始终可以将文件拆分为n个块并使用n个进程来处理每个块(其中n是您可用的单独磁盘的数量......)