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':

  1. 根据文档,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 实现要看。

  2. 这就是 CPython 所做的,CPython 被广泛理解为 Python 的官方参考解释器(如文档中所述,例如,https://docs.python.org/devguide/#other-interpreter-implementations).

也许该论点不像查看 C、C++ 或 ECMAScript 规范的等效论点那样正式或严格。如果这让您感到困扰,那就太糟糕了,因为您不会在 Python 世界中找到那种正式程度。 Python 的文档是它的规范,但它们 也是 文档,适用于使用该语言的普通开发人员,因此不会像 anally 那样定义行为其他语言的正式标准倾向于。当有疑问时,以最自然的方式解释文档并假定 Python 将遵循 principle of least astonishment,如果这不能提供足够的确定性,请相信 CPython 参考解释器。