【问题标题】:Python - How to read a specific line in a text file?Python - 如何读取文本文件中的特定行?
【发布时间】:2017-07-16 12:52:00
【问题描述】:

我有一个巨大的文本文件 (12GB)。这些行是制表符分隔的,第一列包含一个 ID。对于每个 ID,我都想做一些事情。因此,我的计划是从第一行开始,逐行遍历第一列,直到到达下一个ID。

start_line = b
num_lines = 377763316

while b < num_lines:
  plasmid1 = linecache.getline("Result.txt", b-1)
  plasmid1 = plasmid1.strip("\n")
  plasmid1 = plasmid1.split("\t")

  plasmid2 = linecache.getline("Result.txt", b)
  plasmid2 = plasmid2.strip("\n")
  plasmid2 = plasmid2.split("\t")


    if not str(plasmid1[0]) == str(plasmid2[0]):
      end_line = b
      #do something

代码有效,但问题是 linecache 似乎每次都重新加载 txt 文件。如果我不提高性能,代码会运行几年。

如果您知道如何解决问题或知道替代方法,我非常感谢您的帮助!

谢谢, 菲利普

【问题讨论】:

标签: python text readline


【解决方案1】:

我认为numpy.loadtxt() 是要走的路。此外,最好传递 usecols 参数来指定您实际需要文件中的哪些列。 Numpy 包是考虑到高性能而编写的可靠库。

致电loadtxt() 后,您将收到ndarray 回复。

【讨论】:

    【解决方案2】:

    你可以使用itertools:

    from itertools import takewhile
    
    class EqualityChecker(object):
       def __init__(self, id):
           self.id = id
    
       def __call__(self, current_line):
           result = False
           current_id = current_line.split('\t')[0]
    
           if self.id == current_id:
               result = True
    
           return result
    
    
    with open('hugefile.txt', 'r') as f:
       for id in ids:
           checker = EqualityChecker(id)
           for line in takewhile(checker, f.xreadlines()):
               do_stuff(line) 
    

    在外层循环中id实际上可以从第一行获取id不匹配之前的值。

    【讨论】:

      【解决方案3】:

      您应该只打开文件一次,然后遍历这些行。

      with open('Result.txt', 'r') as f:
          aline = f.next()
          currentid = aline.split('\t', 1)[0]
          for nextline in f:
              nextid = nextline.split('\t', 1)[0]
              if nextid != currentid:
                  #do stuff
                  currentid = nextid
      

      你明白了,只需使用普通的 python。 每次迭代只读取一行。拆分中额外的1 参数将仅拆分到第一个选项卡,从而提高性能。使用任何专门的库都不会获得更好的性能。只有简单的 C 语言实现才能胜过这种方法。

      如果您得到AttributeError: '_io.TextIOWrapper' object has,可能是因为您使用的是Python 3.X(请参阅问题io-textiowrapper-object)。试试这个版本:

      with open('Result.txt', 'r') as f:
          aline = f.readline()
          currentid = aline.split('\t', 1)[0]
          while aline != '':
              aline = f.readline()
              nextid = aline.split('\t', 1)[0]
              if nextid != currentid:
                  #do stuff
                  currentid = nextid
      

      【讨论】:

      • 感谢您的评论!我收到以下错误:AttributeError: '_io.TextIOWrapper' object has no attribute 'next' 有什么想法吗?
      • 这是 python 2 vs 3 的不兼容问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-25
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多