我正在创建一个文件编辑系统,并希望创建一个基于行的tell()函数,而不是基于字节的函数。此函数将在open(file)调用的“with循环”内部使用。该函数是包含以下内容的类的一部分:
self.f = open(self.file, 'a+')
# self.file is a string that has the filename in it
以下是原始功能
(如果您想返回行和字节,它也有一个char设置):
def tell(self, char=False):
t, lc = self.f.tell(), 0
self.f.seek(0)
for line in self.f:
if t >= len(line):
t -= len(line)
lc += 1
else:
break
if char:
return lc, t
return lc
我遇到的问题是,这将返回OSError,并且与系统如何遍历文件有关,但我不理解该问题。感谢任何能提供帮助的人。
最佳答案
我有一个较旧的Python 3版本,并且在Linux而不是Mac上运行,但是我能够重新创建非常接近您的错误的内容:
IOError: telling position disabled by next() call
IO错误,不是OS错误,但其他方面相同。十分奇怪的是,我无法使用您的
open('a+', ...)
导致它,但仅当以读取模式打开文件时:open('r+', ...)
。更令人困惑的是,该错误来自
_io.TextIOWrapper
,该类似乎在Python的_pyio.py
文件中定义...我强调“出现”,原因是:TextIOWrapper
具有诸如_telling
之类的属性,我无法在调用_io.TextIOWrapper
的what-it-is对象上进行访问。 TextIOWrapper
中的_pyio.py
类在可读,可写或随机访问文件之间没有任何区别。两者都应该起作用,或者都应该引发相同的IOError
。 无论如何,在进行迭代时,
TextIOWrapper
文件中描述的_pyio.py
类将禁用tell
方法。这似乎是您遇到的问题(评论是我的):def __next__(self):
# Disable the tell method.
self._telling = False
line = self.readline()
if not line:
# We've reached the end of the file...
self._snapshot = None
# ...so restore _telling to whatever it was.
self._telling = self._seekable
raise StopIteration
return line
在
tell
方法中,几乎总是在迭代到达文件末尾之前将break
移出迭代,而禁用_telling
(False
):重置
_telling
的另一种方法是flush
方法,但是如果在进行迭代时调用它,也会失败:IOError: can't reconstruct logical file position
至少在我的系统上,解决此问题的方法是在
seek(0)
上调用TextIOWrapper
,这会将所有内容恢复为已知状态(并在讨价还价中成功调用了flush
):def tell(self, char=False):
t, lc = self.f.tell(), 0
self.f.seek(0)
for line in self.f:
if t >= len(line):
t -= len(line)
lc += 1
else:
break
# Reset the file iterator, or later calls to f.tell will
# raise an IOError or OSError:
f.seek(0)
if char:
return lc, t
return lc
如果这不是您系统的解决方案,那么它至少可以告诉您从哪里开始寻找。
PS:您应该考虑始终返回行号和字符偏移量。可以返回完全不同类型的函数很难处理---调用者丢弃自己不需要的值要容易得多。
关于python - 如何解决 “OSError: telling position disabled by next() call”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29618936/