readlines() 是否保证从当前位置而不是文件开头读取(在所有 Python 实现中)?
Is readlines() guaranteed to read from the current position rather than the beginning of the file (in all Python implementations)?
考虑:
with open('test.txt', 'w') as f:
for i in range(5):
f.write("Line {}\n".format(i))
with open('test.txt', 'r') as f:
f.readline()
for line in f.readlines():
print(line.strip())
这输出
Line 1
Line 2
Line 3
Line 4
也就是说,f
有一个内部迭代器,f.readline()
使用第一行,f.readlines()
读取所有其他行,直到文件末尾。 这是expected/guaranteed从语言的角度来看吗?
我找到的唯一信息来自 docs.python.org,
If you want to read all the lines of a file in a list you can also use list(f)
or f.readlines()
.
我觉得有点模棱两可。
当他们在文档中提到这个技巧时,他们不希望您先 fiddle 使用迭代器。
是的,这是预期的(并且很有用,例如,当您想跳过标题行,然后阅读其余行时)。
如果您想确保阅读所有行,只需在调用 readlines
:
之前倒回文件
f.seek(0)
lines = f.readlines()
关于 readlines
不倒回文件的文档有点稀缺。我做了很多谷歌搜索,这似乎是暗示和自然的。如果你还不服气,你得看看源码(bytesio.c
来自Python 3.6.1 source):
static PyObject *
_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg)
/*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/
{
Py_ssize_t maxsize, size, n;
PyObject *result, *line;
char *output;
CHECK_CLOSED(self);
if (PyLong_Check(arg)) {
maxsize = PyLong_AsSsize_t(arg);
if (maxsize == -1 && PyErr_Occurred())
return NULL;
}
else if (arg == Py_None) {
/* No size limit, by default. */
maxsize = -1;
}
else {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
size = 0;
result = PyList_New(0);
if (!result)
return NULL;
output = PyBytes_AS_STRING(self->buf) + self->pos;
while ((n = scan_eol(self, -1)) != 0) {
self->pos += n;
我在 readline 循环开始后就停止了粘贴。在上面的行中,我们看到代码正在使用 object 的当前 self->pos
值。并且在代码开头没有重置
这就是 readlines() 应该做的。
相信 readlines()
从当前位置而不是从文件开头读取的两个原因是 'guaranteed':
根据文档,open
returns a file object which per the glossary means something that implements the contract defined in the io
module. The io
module docs tell us that .readlines()
将
Read and return a list of lines from the stream.
另请注意,术语 "stream position" 在整个 io
文档中经常使用。我想我不得不承认文档并没有 100% 明确地明确表示 readlines()
将从当前流位置开始读取,而不是从文件的开头(或中间,或随机位置,或根据星期几变化的位置)。但是,我认为可以公平地说 - 鉴于它在 io
文档中确定流具有位置 - 除了从当前流位置读取之外的任何解释都是不正当的,即使我们没有任何真正的-life 实现要看。
这就是 CPython 所做的,CPython 被广泛理解为 Python 的官方参考解释器(如文档中所述,例如,https://docs.python.org/devguide/#other-interpreter-implementations).
也许该论点不像查看 C、C++ 或 ECMAScript 规范的等效论点那样正式或严格。如果这让您感到困扰,那就太糟糕了,因为您不会在 Python 世界中找到那种正式程度。 Python 的文档是它的规范,但它们 也是 文档,适用于使用该语言的普通开发人员,因此不会像 anally 那样定义行为其他语言的正式标准倾向于。当有疑问时,以最自然的方式解释文档并假定 Python 将遵循 principle of least astonishment,如果这不能提供足够的确定性,请相信 CPython 参考解释器。
考虑:
with open('test.txt', 'w') as f:
for i in range(5):
f.write("Line {}\n".format(i))
with open('test.txt', 'r') as f:
f.readline()
for line in f.readlines():
print(line.strip())
这输出
Line 1
Line 2
Line 3
Line 4
也就是说,f
有一个内部迭代器,f.readline()
使用第一行,f.readlines()
读取所有其他行,直到文件末尾。 这是expected/guaranteed从语言的角度来看吗?
我找到的唯一信息来自 docs.python.org,
If you want to read all the lines of a file in a list you can also use
list(f)
orf.readlines()
.
我觉得有点模棱两可。
当他们在文档中提到这个技巧时,他们不希望您先 fiddle 使用迭代器。
是的,这是预期的(并且很有用,例如,当您想跳过标题行,然后阅读其余行时)。
如果您想确保阅读所有行,只需在调用 readlines
:
f.seek(0)
lines = f.readlines()
关于 readlines
不倒回文件的文档有点稀缺。我做了很多谷歌搜索,这似乎是暗示和自然的。如果你还不服气,你得看看源码(bytesio.c
来自Python 3.6.1 source):
static PyObject *
_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg)
/*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/
{
Py_ssize_t maxsize, size, n;
PyObject *result, *line;
char *output;
CHECK_CLOSED(self);
if (PyLong_Check(arg)) {
maxsize = PyLong_AsSsize_t(arg);
if (maxsize == -1 && PyErr_Occurred())
return NULL;
}
else if (arg == Py_None) {
/* No size limit, by default. */
maxsize = -1;
}
else {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
size = 0;
result = PyList_New(0);
if (!result)
return NULL;
output = PyBytes_AS_STRING(self->buf) + self->pos;
while ((n = scan_eol(self, -1)) != 0) {
self->pos += n;
我在 readline 循环开始后就停止了粘贴。在上面的行中,我们看到代码正在使用 object 的当前 self->pos
值。并且在代码开头没有重置
这就是 readlines() 应该做的。
相信 readlines()
从当前位置而不是从文件开头读取的两个原因是 'guaranteed':
根据文档,
open
returns a file object which per the glossary means something that implements the contract defined in theio
module. Theio
module docs tell us that.readlines()
将Read and return a list of lines from the stream.
另请注意,术语 "stream position" 在整个
io
文档中经常使用。我想我不得不承认文档并没有 100% 明确地明确表示readlines()
将从当前流位置开始读取,而不是从文件的开头(或中间,或随机位置,或根据星期几变化的位置)。但是,我认为可以公平地说 - 鉴于它在io
文档中确定流具有位置 - 除了从当前流位置读取之外的任何解释都是不正当的,即使我们没有任何真正的-life 实现要看。这就是 CPython 所做的,CPython 被广泛理解为 Python 的官方参考解释器(如文档中所述,例如,https://docs.python.org/devguide/#other-interpreter-implementations).
也许该论点不像查看 C、C++ 或 ECMAScript 规范的等效论点那样正式或严格。如果这让您感到困扰,那就太糟糕了,因为您不会在 Python 世界中找到那种正式程度。 Python 的文档是它的规范,但它们 也是 文档,适用于使用该语言的普通开发人员,因此不会像 anally 那样定义行为其他语言的正式标准倾向于。当有疑问时,以最自然的方式解释文档并假定 Python 将遵循 principle of least astonishment,如果这不能提供足够的确定性,请相信 CPython 参考解释器。