Python - 有办法通过一行追踪文件对象的当前位置吗

1 投票
4 回答
972 浏览
提问于 2025-04-18 11:18

我有一个测试文件 (不是 Python 脚本),里面包含了多个这样的序列:

测试文件 (不是 Python 脚本)

#Gibberish
#Gibberish
newSeq name-and-details
10 something
20 something
30 something
newSeq name-and-details
10 something
20 something
30 something
#Gibberish
#Gibberish
newSeq name-and-details
...and so forth

然后,我有一个 Python 脚本,它读取这个文件作为输入。对于每一个新的序列,都会创建一个新的 Python 列表来存储内容。

inputFile = open('testFile','r')
moreSeq = True
newLine = inputFile.readline()
while moreSeq:
  while (not ('newSeq' in newLine)):
    newLine = inputFile.readline()
  newList = []
  moreSeq = newList.listEntry(inputFile)
  listDB.append(newList)

但是,当文件对象 inputFile 被传递给 listEntry 方法时,我希望它的位置能指向新的序列的开始,而不是后面的某个索引:

也就是说,我希望它指向 newSeq #1 这一行,而不是 10 something

我该如何将文件对象的位置回溯到前一行,或者按固定行数回溯呢?我觉得使用 seek 方法在这种情况下不太管用。

4 个回答

0

解决这个问题的一个直接方法是使用 itertools.chain,可以这样做:

moreSeq = newList.listEntry(itertools.chain([newline], inputFile))

这样一来,listEntry 方法就能看到一个符合你描述的可迭代对象。不过,我怀疑这并不能解决你在 listEntry 解析行并返回时遇到的问题。因为当那种情况发生时,你可能还想重新读取文件,因为 listEntry 可能会消耗掉其中一行 #Gibberish

我得说,你的代码看起来更像是 C 语言,而不是 Python。我觉得用 for line in f 这种风格的循环来读取行会更清晰。也许重新考虑一下你的方法,让它更符合 Python 语言的风格会更好。

1

我觉得可以用下面的方式来实现相同的效果:

lists = []
with open('testFile','r') as f:
    for line in f:
        if '#Gib' in line:
            pass
        elif 'newSeq' in line:
            lists.append([])
        else:
            lists[-1].append(line)

这样做会返回一个包含所需行的列表的列表。你可以使用任何你想要的数据结构。如果newSeq的名字和细节是唯一的,那么我觉得用哈希表的列表会是一个更好的选择。

1

你可以使用 file.tell() 来查看文件中当前的字节位置,使用 file.seek() 可以把光标移动到你想要的新位置。通过这两个方法,再加上你刚刚读取的行的长度,应该就能轻松实现你想做的事情。

f = open('foo.txt')
f.readline() # output `bar`
f.tell() # output 3
f.seek(0) # go to the start of the file
2

这是一个常见的问题,通常可以通过重新读取这一行来解决,下面的代码就是这样做的:

class SmartReader(object):
    def __init__(self, file):
       self.file = file
       self.lastline = None
    def readline(self):
       if self.lastline is not None:
          ln = self.lastline
          self.lastline = None
          return ln
       return self.file.readline()
    def unreadline(self, line):
       self.lastline = line           


     ...


    fd = SmartReader(open("file.txt"))
    readMore = True
    while readMore:
       line = fd.readline()
       if its_newSeq():
          fd.unreadline(line)
          close_the_previous_sequence()
       else:
          process_the_line()

撰写回答