如何解决“OSError:通过 next() 调用禁用位置" [英] How to solve "OSError: telling position disabled by next() call"

查看:10
本文介绍了如何解决“OSError:通过 next() 调用禁用位置"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个文件编辑系统,并希望创建一个基于行的 tell() 函数而不是基于字节的函数.此函数将在带有 open(file) 调用的带循环"内使用.此函数是具有以下内容的类的一部分:

I am creating a file editing system and would like to make a line based tell() function instead of a byte based one. This function would be used inside of a "with loop" with the open(file) call. This function is part of a class that has:

self.f = open(self.file, 'a+')
# self.file is a string that has the filename in it

以下是原函数(如果您想要行和字节返回,它还有一个字符设置):

The following is the original function (It also has a char setting if you wanted line and byte return):

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 并且它与系统如何迭代文件有关,但我不明白这个问题.感谢任何可以提供帮助的人.

The problem I'm having with this is that this returns an OSError and it has to do with how the system is iterating over the file but I don't understand the issue. Thanks to anyone who can help.

推荐答案

我有一个旧版本的 Python 3,我使用的是 Linux 而不是 Mac,但我能够重新创建与您的错误非常接近的内容:

I have an older version of Python 3, and I'm on Linux instead of a Mac, but I was able to recreate something very close to your error:

IOError: telling position disabled by next() call

IO 错误,不是 OS 错误,但其他方面相同.奇怪的是,我无法使用您的 open('a+', ...) 导致它,但仅在以读取模式打开文件时才导致: open('r+', ...).

An IO error, not an OS error, but otherwise the same. Bizarrely enough, I couldn't cause it using your open('a+', ...), but only when opening the file in read mode: open('r+', ...).

更令人困惑的是,该错误来自 _io.TextIOWrapper,该类似乎被定义在 Python 的 _pyio.py 文件中...我强调出现",因为:

Further muddling things is that the error comes from _io.TextIOWrapper, a class that appears to be defined in Python's _pyio.py file... I stress "appears", because:

  1. 该文件中的 TextIOWrapper 具有诸如 _telling 之类的属性,我无法在调用自身 _io 的任何对象上访问这些属性.TextIOWrapper.

  1. The TextIOWrapper in that file has attributes like _telling that I can't access on the whatever-it-is object calling itself _io.TextIOWrapper.

_pyio.py 中的 TextIOWrapper 类不区分可读、可写或随机访问的文件.要么两者都可以工作,要么两者都应该引发相同的 IOError.

The TextIOWrapper class in _pyio.py doesn't make any distinction between readable, writable, or random-access files. Either both should work, or both should raise the same IOError.

无论如何,_pyio.py 文件中描述的 TextIOWrapper 类在迭代过程中禁用 tell 方法.这似乎是您遇到的问题(评论是我的):

Regardless, the TextIOWrapper class as described in the _pyio.py file disables the tell method while the iteration is in progress. This seems to be what you're running into (comments are mine):

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 处于禁用状态():

In your tell method, you almost always break out of the iteration before it reaches the end of the file, leaving _telling disabled (False):

另一种重置 _telling 的方法是 flush 方法,但如果在迭代过程中调用它也会失败:

One other way to reset _telling is the flush method, but it also failed if called while the iteration was in progress:

IOError: can't reconstruct logical file position

解决这个问题的方法,至少在我的系统上,是在 TextIOWrapper调用 seek(0),它将所有内容恢复到一个已知状态(并在交易中成功调用 flush):

The way around this, at least on my system, is to call seek(0) on the TextIOWrapper, which restores everything to a known state (and successfully calls flush in the bargain):

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

如果这不是您系统的解决方案,它至少可能会告诉您从哪里开始寻找.

If that's not the solution for your system, it might at least tell you where to start looking.

PS:您应该考虑总是同时返回行号和字符偏移量.可以返回完全不同类型的函数很难处理——调用者扔掉她或她不需要的值要容易得多.

PS: You should consider always returning both the line number and the character offset. Functions that can return completely different types are hard to deal with --- it's a lot easier for the caller to just throw away the value her or she doesn't need.

这篇关于如何解决“OSError:通过 next() 调用禁用位置"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆