Python 如何解决;OSError:通知位置被next()调用禁用;
我正在创建一个文件编辑系统,希望创建一个基于行的tell()函数,而不是基于字节的函数。此函数将在带有open(file)调用的“with循环”中使用。此函数是类的一部分,该类具有:Python 如何解决;OSError:通知位置被next()调用禁用;,python,file-io,error-handling,next,Python,File Io,Error Handling,Next,我正在创建一个文件编辑系统,希望创建一个基于行的tell()函数,而不是基于字节的函数。此函数将在带有open(file)调用的“with循环”中使用。此函数是类的一部分,该类具有: self.f = open(self.file, 'a+') # self.file is a string that has the filename in it 以下是原始函数 (如果需要行和字节返回,它还有一个char设置): 我遇到的问题是,这会返回一个操作错误,它与系统如何迭代文件有关,但我不理解这个问
self.f = open(self.file, 'a+')
# self.file is a string that has the filename in it
以下是原始函数
(如果需要行和字节返回,它还有一个char设置):
我遇到的问题是,这会返回一个操作错误,它与系统如何迭代文件有关,但我不理解这个问题。感谢所有能够提供帮助的人。我有一个较旧版本的Python 3,我使用的是Linux而不是Mac,但我能够重新创建一些与您的错误非常接近的东西:
IOError:告诉位置被next()调用禁用
IO错误,不是操作系统错误,但在其他方面是相同的。奇怪的是,我无法使用您的open('a+',…)
,但只能在读取模式下打开文件时使用:open('r+',…)
更令人困惑的是,错误来自\u io.TextIOWrapper
,一个似乎在Python的\u pyio.py
文件中定义的类。。。我强调“出现”,因为:
TextIOWrapper
具有类似\u的属性,告诉我无法访问调用自身的对象\u io.TextIOWrapper
\u pyio.py
中的TextIOWrapper
类不区分可读、可写或随机访问文件。要么两者都可以工作,要么两者都会引发相同的IOError
\u pyio.py
文件中描述的TextIOWrapper
类在迭代过程中禁用tell
方法。这似乎就是你遇到的(评论是我的):
def\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
#禁用tell方法。
自欺欺人
line=self.readline()
如果不是直线:
#我们已经到了文件的末尾。。。
self.\u快照=无
#…所以,让你回到过去。
self.\u telling=self.\u seakable
提出停止迭代
回程线
在tell
方法中,您几乎总是在迭代到达文件末尾之前中断
,使\u telling
处于禁用状态(False
):
重置的另一种方法是flush
方法,但如果在迭代过程中调用该方法,也会失败:
IOError:无法重建逻辑文件位置
至少在我的系统上,解决这个问题的方法是在TextIOWrapper
上调用seek(0)
,这会将所有内容恢复到已知状态(并在交易中成功调用flush
):
def tell(self,char=False):
t、 lc=self.f.tell(),0
self.f.seek(0)
对于self.f中的行:
如果t>=len(行):
t-=len(直线)
lc+=1
其他:
打破
#重置文件迭代器,或稍后调用f.tell will
#引发IOError或OSError:
f、 搜索(0)
如果是字符:
返回信用证,t
返回信用证
如果这不是您的系统的解决方案,它至少可以告诉您从哪里开始寻找
PS:你应该考虑总是返回行数和字符偏移量。返回完全不同类型的函数是很难处理的——调用者更容易扔掉她或她不需要的值。
我不知道这是否是最初的错误,但如果你试图在一个文件的逐行迭代中调用f.tell(),你会得到同样的错误,就像这样:
with open(path, "r+") as f:
for line in f:
f.tell() #OSError
可由以下内容轻松替代:
with open(path, mode) as f:
line = f.readline()
while line:
f.tell() #returns the location of the next line
line = f.readline()
只是针对此问题的快速解决方法:
无论如何,当您从一开始就迭代文件时,只需使用专用变量跟踪您的位置:
file_pos = 0
with open('file.txt', 'rb') as f:
for line in f:
# process line
file_pos += len(line)
现在file\u pos
将永远是file.tell()
将告诉您的内容。请注意,这仅适用于ASCII文件,因为tell和seek使用字节位置。以行为基础,将字符串从字节转换为unicode字符串很容易 我遇到了同样的错误:OSError:telling position被next()调用禁用,并通过在打开文件时添加“rb”模式解决了这个问题。如果没有看到其他类,很难回答。(我无法仅使用函数在Linux上复制它。)您可能需要阅读,这可以为您(和我们)提供一些附加信息。我的第一个问题是,因为这是一个操作系统错误:你的操作系统是什么?另外(可能相关):为什么/如何在其中查找?我以附加模式打开它,因为在创建实例之前,假定该文件不存在。(如您所知,我确信,“a”模式会在文件不存在时创建该文件)。我希望能够在代码中节省空间,以便检查文件是否存在。我的操作系统是MacOSXYosemite,但我认为这与苹果无关。非常感谢你的帮助!我的问题是,在文件迭代过程中(逐行)无法调用(内置)tell()方法。我找到了解决这个问题的方法,你的回答真的很有帮助。再次感谢@BrandonGomes:你介意和我分享你的解决方案吗?对不起@marscher,我没有这个代码了。它来自一台旧电脑。我认为答案是存储一些关于文件迭代器的元数据。你可以随时重写下一个函数。这是最方便的方法!这是一个多么愚蠢的问题,谢谢:)在py3中,由于“rb”行是您所期望的(包括\r\n
中的行终止符)-因此这对于倒带到行的开始非常有效-漂亮!
file_pos = 0
with open('file.txt', 'rb') as f:
for line in f:
# process line
file_pos += len(line)