我正在创建一个文件编辑系统,并希望创建一个基于行的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/

    10-12 20:56