首页 > 解决方案 > Django - 如果 csv 文件包含空行,则 CSV 阅读器不起作用

问题描述

我在视图中有一个函数,用于上传 CSV 数据并写入数据库。如果 CSV 文件没有任何空行,则该功能可以正常工作。但是,如果 CSV 文件有任何空行,则该函数根本不会读取任何数据。以下是代码的摘录:

data_set = csv_file.read().decode('utf-8')
io_string = io.StringIO(data_set)
next(io_string)
created = None
created_records = 0
for column in csv.reader(io_string, delimiter=',', quotechar="|"):
    _, created = GrowerMaster.objects.update_or_create(
        grower_no           =column[0],
        surname             =column[1],
        name                =column[2],
        initials            =column[3],
        area                =column[11],
        national_id         =column[15],
        contractor          =column[21]
    )

    if created:
        created_records+=1


if created is None:
    messages.warning(request, "No records were read from file. Please check the file and try again")

if created_records > 0:
    messages.success(request, f"{created_records} new records have been imported successfully")

else:
    messages.warning(request, "No new records were imported.")  

我在哪里以及如何解决此问题,以便仍然可以成功处理带有空行的 csv 文件。

下面的屏幕截图显示了导致问题的行。如果我手动删除该行,则文件上传成功。

在此处输入图像描述

标签: djangopython-3.x

解决方案


在解析行之前检查它是否具有所需的列数。否则,您将尝试访问不存在的列并最终崩溃。

for column in csv.reader(io_string, delimiter=',', quotechar="|"):
    if len(column) >= HEADER_LENGTH:
        _, created = GrowerMaster.objects.update_or_create(
            grower_no           =column[0],
            surname             =column[1],
            name                =column[2],
            initials            =column[3],
            area                =column[11],
            national_id         =column[15],
            contractor          =column[21]
        )

或者尝试处理异常(这可能是IndexError):

for column in csv.reader(io_string, delimiter=',', quotechar="|"):
    try:
        _, created = GrowerMaster.objects.update_or_create(
            grower_no           =column[0],
            surname             =column[1],
            name                =column[2],
            initials            =column[3],
            area                =column[11],
            national_id         =column[15],
            contractor          =column[21]
        )
        if created:
            created_records+=1
    except IndexError:
        # skip the row
        pass

推荐阅读