将大文件划分为多个较小的随机写入多个文件

时间:2016-08-03 23:15:57

标签: python io

这有点令人尴尬,但我对一个相当简单(至少应该是)的任务有点困难:

我希望有一个脚本可以获取一个大文本文件(几个GB)并分成更小的部分。然而,该分区应该不是按照行的顺序发生,而是基于匹配的字符串模式,这样每个行/条目应该基于起始字符进行分类。所以算法看起来像这样:

  1. 在dict {key:pattern}
  2. 中定义类别
  3. 定义匹配/分类功能
  4. 打开输入文件并开始迭代条目
  5. 对每个条目进行分类
  6. 将条目写入相应的文件
  7. 我遇到的问题是输出文件,特别是:

    • 我是否提前申报?类别的数量可能会因实例而异,因此我在技术上不知道要打开多少个文件。此外,无法保证每个类别都在输入数据中表示,因此创建没有内容的文件会很愚蠢。

      • 如果我遍历dict中的类别,并打开一堆文件;如何跟踪哪个文件的哪个键?有另一个字典,即dict2 {key : file}感觉有点矫枉过正,也不是特别漂亮......

      • 如果我不提前打开文件,每次需要写入文件时打开/关闭新的io频道,我认为会有很大的开销。

    仅在需要时打开文件的另一个复杂因素如下:每次我运行脚本时我都要覆盖生成的文件。但是如果我在主循环中有文件访问权限,我将需要打开文件进行追加。

    以下是我到目前为止的测试代码:

    from itertools import islice
    import random, sys, os
    
    cats = {
        "key1" : "<some pattern>",
        "key2" : "<some other pattern>",
        "key3" : "<yet another pattern>"}
    
    def delta(x, s):
        return sum([int(c0 != c1) for c0,c1 in zip(x,s)])
    
    def categorize_str(x, cats):
        d = {cat : delta(x,tag) for cat,tag in cats.items()}
        return min(d, key=d.get)
    
    def main():
        file = sys.argv[1]
        nseq = None if len(sys.argv) < 3 else int(sys.argv[2])
    
        path = os.path.dirname(file)
        base = os.path.basename(file))
        (name,ext) = os.path.splitext(base)
        for k in cats.keys():  # <----
            outfile = os.path.join(path, ''.join([name, "_", k, ext])
            # what do I do with outfile now???
    
        read = ... # library call to that opens input file and returns an iterator
        for rec in islice(read,nseq):
            c = categorize_str(rec, cats)
            # depending on c, write to one of the "outfile"s
    
    if __name__ == "__main__":
        main()
    

1 个答案:

答案 0 :(得分:0)

想法:定义一个名为Pattern的类。这里有几个成员变量:一个是你已经拥有的"<some pattern>";另一个是文件名;第三种是用于下一次调用该文件的open()的模式。该模式将是第一次“w”(创建一个新文件),然后您的代码将更改为“w +”,因此您将附加任何后续写入。这个类的实例作为值进入“cats”字典。这解决了您对使用多个字典的异议 - 处理一个类别所需的所有信息都保存在一个对象中。它还允许您避免创建空文件。

也许操作系统可以很好地解决对几个文件进行大量小附加的问题。如果这是性能瓶颈,那么您还需要做更多的工作(也许您可以在一步完成之前将一些更新缓存在列表中)。