Python “的含义;OSError:通知位置被next()调用禁用;错误?
这几乎和我的问题一样。虽然旧问题已经得到了一些有用的解决方法,但错误的含义并不清楚。我想知道是否有人能对此发表评论 我正在学习Python,并大致遵循以下步骤。我在Fedora 23上以交互方式输入了以下内容:Python “的含义;OSError:通知位置被next()调用禁用;错误?,python,python-3.x,file,Python,Python 3.x,File,这几乎和我的问题一样。虽然旧问题已经得到了一些有用的解决方法,但错误的含义并不清楚。我想知道是否有人能对此发表评论 我正在学习Python,并大致遵循以下步骤。我在Fedora 23上以交互方式输入了以下内容: $python3 Python 3.4.3(默认,2016年8月9日,15:36:17) linux上的[GCC 5.3.1 20160406(Red Hat 5.3.1-6)] 有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。 >>>打开(“myfile”、“r”)作为
$python3
Python 3.4.3(默认,2016年8月9日,15:36:17)
linux上的[GCC 5.3.1 20160406(Red Hat 5.3.1-6)]
有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。
>>>打开(“myfile”、“r”)作为文件:
... 对于文件中的l:
... 打印(“下一行:\“{}\”。格式(l))
... 打印(“当前位置{:4d}”。格式(file.tell())
myfile
包含几行文本。输出:
下一行:“这是第0行
"
回溯(最近一次呼叫最后一次):
文件“”,第4行,在
OSError:通知位置被next()调用禁用
用谷歌搜索这个错误会得到惊人的6个结果。Windows10上Cygwin上的Python3.6.4也是如此
编辑:
文本文件的tell()
方法是:
以不透明数字返回当前流位置。号码
通常不表示基础二进制文件中的字节数
储藏室
“不透明数字”似乎表明我不能直接打印它。因此,我将第二个
print()
调用替换为pos=file.tell()
。相同的结果。消息的意思与它所说的完全相同:因为您已对该文件调用了next()
,因此已禁用对该文件使用tell()
看起来您可能没有调用next
,但是for
循环会隐式调用它。用于循环的:
for element in thing:
do_stuff_with(element)
语法上的糖是什么
iterator = iter(thing) # the real implementation doesn't use a variable
while True:
try:
element = next(iterator) # here's the next() call
except StopIteration:
break
do_stuff_with(element)
对于文件,iter(file)
返回文件,循环调用文件上的next
至于为什么调用next
会禁用tell()
,这是为了提高效率。这种情况只发生在文本文件(特别是io.TextIOWrapper
)上,它们必须做大量工作来支持tell
;关闭tell
支持可以让他们跳过该工作。使next
disabletell
的原始提交消息是“通过禁用快照更新来加快next()”,这表明这是为了提高效率
对于历史上下文,对tell
和其他文件方法没有考虑的next
使用隐藏缓冲区,导致tell
(和其他文件方法)在对文件的迭代过程中产生不太有意义的结果。当前IO实现将能够在迭代期间支持tell()
,但IO.TextIOWrapper
无论如何都会阻止此类调用。next
和其他方法之间的历史不兼容可能是导致在迭代期间禁用部分文件功能的原因
你没有要求解决办法,但为了那些最终在本页上寻找解决办法的人的利益,我要提到这一点
for line in iter(file.readline, ''):
...
将允许您在不禁用tell
的情况下迭代文本文件的行。(您可以对iter中的行(file.readline,b'')使用)
处理二进制文件,但没有太多意义,因为告诉禁用机制不适用于二进制文件。)如果您的文本文件太大,有两种解决方案:
使用file.readline()
而不是next()
使用offset+=len(line)
而不是file.tell()
在以文本模式打开的文件上,tell()
的“不透明性”意味着,由于行尾转换以及文本文件和二进制文件之间可能存在的任何其他平台特定差异,结果可能与从文件中接收到的字符数不匹配。它唯一的好处就是seek()
稍后返回到相同的位置。但是,该值仍然是一个普通的整数,如果您愿意,没有什么可以阻止您将其打印出来。OP没有显式调用next()
…您的回答的其余部分对我来说听起来更像是纯粹的推测。@martineau:没有显式的next
调用,但是for
隐式调用next
。至于答案的其余部分,主要是推测性的,但是旧的next
/其他方法的不兼容性被记录下来,并且在禁用告知时实现会跳过工作。@martineau:答案现在应该不那么推测性了。这肯定是一个改进,但我认为你至少应该向OP解释他们对文件中的l的是如何导致对next()
的隐式调用的,因为这显然不明显,而且他们似乎不理解文件和迭代器是如何工作的。@martineau:解释扩展了。
with open(path, mode) as file:
while True:
line = file.readline()
if not line:
break
file.tell()
offset = 0
with open(path, mode) as file:
for line in file:
offset += len(line)