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

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

问题描述

我正在创建一个文件编辑系统,并希望使用一个基于行的tell()函数,而不是基于字节的。这个函数将在打开(文件)调用的with loop中使用。此功能是具有以下功能的类的一部分:

  self.f = open(self.file,'a +')
#self.file是一个字符串,其中有文件名

以下是原始函数
(如果你想要返回字符串,它也有一个char设置):

  def tell(self,char = False):
t,lc = self.f.tell(),0
self.f.seek(0)
for self.f中的行:
如果t> ; = len(行):
t - = len(行)
lc + = 1
else:
break
如果char:
return lc, t
return lc

我遇到的问题是这会返回一个OSError它与系统如何迭代文件有关,但我不明白这个问题。感谢任何有帮助的人。

解决方案

我有一个旧版本的Python 3,而我在Linux而不是Mac,但是我能够重新创建一个非常接近你的错误的东西:

  IOError:通过next()调用

一个 IO 错误,而不是 OS 错误,但是否则相同。奇怪的是,我不能使用您的打开('a +',...),但只有在阅读模式下打开文件时:打开('r +',...)



更糟糕的是,错误来自 _io .TextIOWrapper ,一个出现的类在Python的 _pyio.py 文件中定义...我强调出现,因为:


  1. 该文件中的 TextIOWrapper _telling 我无法访问任何调用它的对象 _io.TextIOWrapper


  2. _pyio.py 中的 TextIOWrapper 对可读,可写或随机访问文件进行区分。两者都应该工作,或者两者都应该提出相同的 IOError


无论如何, _pyio.py 文件中描述的 TextIOWrapper 类禁用 tell 方法,而迭代正在进行。这似乎是你正在进行的(意见是我的):

  def __next __ self):
#禁用tell方法。
self._telling = False
line = self.readline()
如果不是行:
#我们已经到达文件的最后...
self ._snapshot =无
#...所以恢复_telling到它是什么。
self._telling = self._seekable
raise StopIteration
return line



<在您的告诉方法中,在到达文件结尾之前,您几乎总是 break 留下 _telling disabled( False ):



_telling 的方法是 flush 方法,但是如果在迭代过程中调用,它也失败: p>

  IOError:无法重建逻辑文件位置
/ pre>

这个方法至少在我的系统上是调用 seek(0) c $ c> TextIOWrapper ,将所有内容恢复到已知状态(并成功调用 flush ):
$ b

  def tell(self,char = False):
t,lc = self.f.tell(),0
self.f.seek(0)
for self.f中的行:
如果t> = len(行):
t - = len(行)
lc + = 1
else:
break
#重置文件迭代器,或稍后调用f.tell将
#引发IOError或OSError:
f.seek (0)
如果char:
return lc,t
return lc

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



PS:你应该考虑总是返回行号和字符偏移。可以返回完全不同类型的函数很难处理 - 呼叫者只需丢弃她或她不需要的值就容易得多。


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

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.

解决方案

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

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+', ...).

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. The TextIOWrapper in that file has attributes like _telling that I can't access on the whatever-it-is object calling itself _io.TextIOWrapper.

  2. 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.

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

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

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

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: 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天全站免登陆