我正在写一个Python脚本来读取一个文件,当我到达文件的某一节时,最终读取该节中那些行的方式取决于该节中也给出的信息。所以我发现 此处 我可以用这样的东西
fp = open('myfile')
last_pos = fp.tell()
line = fp.readline()
while line != '':
if line == 'SPECIAL':
fp.seek(last_pos)
other_function(fp)
break
last_pos = fp.tell()
line = fp.readline()
然而,我现在的代码结构是这样的。
fh = open(filename)
# get generator function and attach None at the end to stop iteration
items = itertools.chain(((lino,line) for lino, line in enumerate(fh, start=1)), (None,))
item = True
lino, line = next(items)
# handle special section
if line.startswith['SPECIAL']:
start = fh.tell()
for i in range(specialLines):
lino, eline = next(items)
# etc. get the special data I need here
# try to set the pointer to start to reread the special section
fh.seek(start)
# then reread the special section
但这种方法给出了以下错误:
通过调用next()告诉位置禁用
有什么办法可以防止这种情况的发生吗?
将文件作为迭代器使用 (例如调用 next()
上或用在 for
循环)使用的是内部缓冲区;实际的文件读取位置在文件的更远处,使用 .tell()
不会给你下一行的位置让步。
如果你需要来回寻找,解决的办法是不使用 next()
直接在文件对象上,但使用 file.readline()
仅仅是。你仍然可以使用迭代器来实现,使用两个参数版本的 iter()
:
fileobj = open(filename)
fh = iter(fileobj.readline, '')
呼叫 next()
关于 fileiterator()
将调用 fileobj.readline()
直到该函数返回一个空字符串。实际上,这就创建了一个文件迭代器,这个迭代器会在 不 使用内部缓冲区。
演示。
>>> fh = open('example.txt')
>>> fhiter = iter(fh.readline, '')
>>> next(fhiter)
'foo spam eggs\n'
>>> fh.tell()
14
>>> fh.seek(0)
0
>>> next(fhiter)
'foo spam eggs\n'
请注意,你的 enumerate
链可以简化为。
items = itertools.chain(enumerate(fh, start=1), (None,))
虽然我不知道你为什么会认为... (None,)
这里需要哨兵。StopIteration
仍然会被提拔,尽管多了一个 next()
稍后再打。
要阅读 specialLines
计行 itertools.islice()
:
for lino, eline in islice(items, specialLines):
# etc. get the special data I need here
你可以直接在上面循环 fh
而不是使用无限循环和 next()
这里也有电话。
with open(filename) as fh:
enumerated = enumerate(iter(fileobj.readline, ''), start=1):
for lino, line in enumerated:
# handle special section
if line.startswith['SPECIAL']:
start = fh.tell()
for lino, eline in islice(items, specialLines):
# etc. get the special data I need here
fh.seek(start)
但请注意,你的行号仍然会递增,甚至当你回溯时也是如此。
然而,你可能想要重构你的代码,以避免重新读取文件的部分。
我不是Python第3版的专家,但看起来你是在使用 generator
该 yields
从文件中读取的行。因此你只能有单边的方向。
你必须使用另一种方法。