在python中读取大csv文件的行

Shw*_*eta 5 python csv file-io generator

我有一个非常大的 csv 文件,无法完全加载到内存中。所以我想一块一块地读取它,将它转换成 numpy 数组,然后再做一些处理。

我已经检查过: Lazy Method for Reading Big File in Python?

但这里的问题是它是一个普通的阅读器,我无法在 csvReader 中找到任何指定大小的选项。

此外,由于我想将行转换为 numpy 数组,因此我不想将任何行读成两半,所以我想要一些可以在阅读器中指定“行数”的东西,而不是指定大小。

是否有任何内置功能或简单的方法来做到这一点。

dan*_*ano 2

不会csv.reader将整个文件读入内存。当您迭代对象时,它会逐行惰性地迭代文件reader。因此,您可以像平常一样使用reader,但是break在您读取了您想要读取的行数之后的迭代中。您可以在用于实现该reader对象的C 代码中看到这一点。

Initializer for the reader objecT:
static PyObject *
csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args)
{
    PyObject * iterator, * dialect = NULL;
    ReaderObj * self = PyObject_GC_New(ReaderObj, &Reader_Type);

    if (!self)
        return NULL;

    self->dialect = NULL;
    self->fields = NULL;
    self->input_iter = NULL;
    self->field = NULL;
    // stuff we dont care about here
    // ...
    self->input_iter = PyObject_GetIter(iterator);  // here we save the iterator (file object) we passed in
    if (self->input_iter == NULL) {
        PyErr_SetString(PyExc_TypeError,
                        "argument 1 must be an iterator");
        Py_DECREF(self);
        return NULL;
    }

static PyObject *
Reader_iternext(ReaderObj *self)  // This is what gets called when you call `next(reader_obj)` (which is what a for loop does internally)
{
    PyObject *fields = NULL;
    Py_UCS4 c;
    Py_ssize_t pos, linelen;
    unsigned int kind;
    void *data;
    PyObject *lineobj;

    if (parse_reset(self) < 0)
        return NULL;
    do {
        lineobj = PyIter_Next(self->input_iter);  // Equivalent to calling `next(input_iter)`
        if (lineobj == NULL) {
            /* End of input OR exception */
            if (!PyErr_Occurred() && (self->field_len != 0 ||
                                      self->state == IN_QUOTED_FIELD)) {
                if (self->dialect->strict)
                    PyErr_SetString(_csvstate_global->error_obj,
                                    "unexpected end of data");
                else if (parse_save_field(self) >= 0)
                    break;
            }
            return NULL;
        }
Run Code Online (Sandbox Code Playgroud)

如您所见,内部next(reader_object)调用next(file_object)。因此,您将逐行迭代两者,而不将整个内容读入内存。