如何解决“OSError:通过next()调用禁用的位置” [英] How to solve "OSError: telling position disabled by next() call"
问题描述
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
文件中定义...我强调出现,因为:
-
该文件中的
TextIOWrapper
_telling
我无法访问任何调用它的对象_io.TextIOWrapper
。 -
_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
):
$ bdef 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:
The
TextIOWrapper
in that file has attributes like_telling
that I can't access on the whatever-it-is object calling itself_io.TextIOWrapper
.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 sameIOError
.Regardless, the
TextIOWrapper
class as described in the_pyio.py
file disables thetell
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 alwaysbreak
out of the iteration before it reaches the end of the file, leaving_telling
disabled (False
):One other way to reset
_telling
is theflush
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 theTextIOWrapper
, which restores everything to a known state (and successfully callsflush
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屋!