python逐行读取更大的csv

时间:2018-06-29 08:03:21

标签: python pandas csv

您好,我有巨大的csv文件(1GB),可以更新(服务器通常会添加新值)

我想在python中逐行读取此文件(不将所有文件加载到内存中),我想“实时”读取此文件

这是我的csv文件的示例:

id,name,lastname
1,toto,bob
2,tutu,jordan
3,titi,henri

在我的示例中,我想第一次获取文件的标题(列名):id,name,lastname

第二次,我想逐行读取此文件而不将所有文件加载到内存中

第三次我想尝试在10秒之间读取新值(例如,使用sleep(10))

我使用熊猫搜索实际解决方案 我读了这个话题: Reading a huge .csv file

import pandas as pd
chunksize = 10 ** 8
for chunk in pd.read_csv(filename, chunksize=chunksize):
    process(chunk)

但是我不理解, 1)我不知道我的csv文件的大小,如何定义chunksize? 2)当我完成阅读后,如何对熊猫说以尝试在10秒之间读取新值(例如)?

感谢您的帮助

3 个答案:

答案 0 :(得分:1)

首先,1GB不是巨大-几乎任何现代设备都可以将其保留在其工作内存中。其次,pandas不允许您浏览CSV文件,您只能告诉它要“加载”多少数据-如果您要执行更高级的CSV,我建议使用内置的csv模块处理。

不幸的是,csv模块的reader()将为您的文件生成一个穷举的迭代器,因此您不能仅将其构建为简单的循环并等待下一行可用-您必须手动收集新行,然后将其添加到其中以达到所需的效果,例如:

import csv
import time

filename = "path/to/your/file.csv"

with open(filename, "rb") as f:  # on Python 3.x use: open(filename, "r", newline="")
    reader = csv.reader(f)  # create a CSV reader
    header = next(reader)  # grab the first line and keep it as a header reference
    print("CSV header: {}".format(header))
    for row in reader:  # iterate over the available rows
        print("Processing row: {}".format(row))  # process each row however you want
    # file exhausted, entering a 'waiting for new data' state where we manually read new lines
    while True:  # process ad infinitum...
        reader = csv.reader(f.readlines())  # create a CSV reader for the new lines
        for row in reader:  # iterate over the new rows, if any
            print("Processing new row: {}".format(row))  # process each row however you want
        time.sleep(10)  # wait 10 seconds before attempting again

当心可能会破坏该过程的极端情况-例如,如果您尝试在添加新行时读取它们,则某些数据可能会丢失/拆分(取决于用于添加的刷新机制)删除读者可能会损坏的前几行,等等。如果可能的话,我建议控制CSV写入过程,以使其明确告知您的处理例程。

更新:上面是逐行处理CSV文件的过程,它永远不会完全加载到工作内存中。实际上唯一会在内存中加载多行的部分是文件更新发生时,它会拾取所有新行,因为这样可以更快地处理它们,除非您期望两行之间有数百万行更新检查,对内存的影响可以忽略不计。但是,如果您还希望逐行处理该零件,请按以下步骤操作:

import csv
import time

filename = "path/to/your/file.csv"

with open(filename, "rb") as f:  # on Python 3.x use: open(filename, "r", newline="")
    reader = csv.reader(f)  # create a CSV reader
    header = next(reader)  # grab the first line and keep it as a header reference
    print("CSV header: {}".format(header))
    for row in reader:  # iterate over the available rows
        print("Processing row: {}".format(row))  # process each row however you want
    # file exhausted, entering a 'waiting for new data' state where we manually read new lines
    while True:  # process ad infinitum...
        line = f.readline()  # collect the next line, if any available
        if line.strip():  # new line found, we'll ignore empty lines too
            row = next(csv.reader([line]))  # load a line into a reader, parse it immediately
            print("Processing new row: {}".format(row))  # process the row however you want
            continue  # avoid waiting before grabbing the next line
        time.sleep(10)  # wait 10 seconds before attempting again 

答案 1 :(得分:0)

块大小是一次读取的行数,因此它不取决于文件大小。在文件末尾for循环将结束。 块的大小取决于用于处理的最佳数据大小。在某些情况下1GB不是问题,因为它可以容纳在内存中,并且您不需要块。如果一次加载1GB不能正常工作,则可以选择1M行chunksize = 1e6,因此,如果行长大约20个字母,则小于100M,这似乎很低,但是您可能会有所不同该参数取决于您的条件。

当您需要阅读更新的文件时,只需重新启动for循环即可。

如果您不想仅阅读整个文件就知道它没有更改,可以查看它的修改时间(details here)。如果没有更改,请跳过阅读。

如果问题是关于10秒钟后的阅读,则可以无限循环地进行睡眠,例如:

import time

while True:
    do_what_you_need()
    time.sleep(10)

实际上,该周期将超过10秒,因为do_what_you_need()也需要时间。

答案 2 :(得分:0)

如果问题是有关读取文件尾部的问题,我不知道在熊猫中实现此目的的好方法,但是您可以采取一些解决方法。

第一个想法是只读取没有熊猫的文件,并记住最后一个位置。下次您需要阅读时,可以使用seek。或者,您可以尝试使用StringIO作为pandas.read_csv

的来源来实现熊猫搜索和读取

另一种解决方法是使用Unix命令tail截断最后n行,如果您确定在那里添加的次数不太多。它会读取整个文件,但是比读取和解析所有熊猫行要快得多。在很长的文件上,仍然寻求在理论上更快。在这里,您需要检查是否添加了太多行(您看不到最后处理的ID),在这种情况下,您需要加长尾巴或读取整个文件。

所有涉及其他代码,逻辑和错误的内容。其中之一是,最后一行可能会中断(如果您正在阅读时正在写的话)。因此,我最喜欢的方式就是从txt文件切换到sqlite,sqlite是SQL兼容的数据库,该数据库将数据存储在文件中,并且不需要特殊的过程即可访问它。它具有python library,使其易于使用。它将以长文件,同时进行读写的方式处理所有员工,仅读取您需要的数据。只需保存上一个已处理的ID,然后像这样SELECT * FROM table_name WHERE id > last_proceesed_id;发出请求即可。好吧,这只有在您还控制服务器代码并且可以以这种格式保存的情况下才有可能。