我正在创建一个文件编辑系统,并希望创建一个基于行的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 错误,而不是一个 操作系统 错误,但在其他方面是相同的。奇怪的是,我无法使用your引起它open('a+', ...),但仅当以读取模式打开文件时:open('r+', ...)。
open('a+', ...)
open('r+', ...)
更令人困惑的是,错误来自_io.TextIOWrapper,一个 似乎 在Python的_pyio.py文件中定义的类…我强调“出现”,因为:
_io.TextIOWrapper
_pyio.py
该TextIOWrapper文件中的的属性类似于_telling我无法调用调用它的what-it-is对象_io.TextIOWrapper。
TextIOWrapper
_telling
中的TextIOWrapper类在_pyio.py可读,可写或随机访问文件之间没有任何区别。两者都应该起作用,或者两者都应该提高相同IOError。
IOError
无论如何,文件中TextIOWrapper描述的类 会 在进行迭代时 禁用该 方法 。这似乎是您遇到的问题(评论是我的):_pyio.py tell
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):
break
False
重置方法的另一种方法_telling是该flush方法,但是如果在进行迭代时调用该方法,也会失败:
flush
IOError: can't reconstruct logical file position
解决这个问题的办法,至少我的系统上,就是要 叫seek(0)上了TextIOWrapper,这一切都恢复到已知状态(成功调用flush在讨价还价中):
seek(0)
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:您应该考虑 始终 返回行号和字符偏移量。可以返回完全不同类型的函数很难处理—调用者丢弃自己不需要的值要容易得多。