上传固定格式的CSV文件

6 投票
9 回答
1314 浏览
提问于 2025-04-17 10:37

我有一个 .csv 文件,用户需要下载这个文件,输入一些数据,然后再上传到我的网站上。

有没有更好的方法来确保数据能够成功上传,基于我下面的代码片段?我还应该检查些什么呢?使用方言(dialect)会不会更好?

def import(resident_file):

    try:
        file = resident_file.file.path
        reader = csv.reader(open(file, 'rU'), delimiter=',', quotechar='"')
        headerline = reader.next()

        for row in reader:
            try:
                # do stuff

            except Exception, e:
                print e

    except Exception, e:
        print e

我遇到的一个问题是,当用户打开文件、输入数据并保存时,分隔符会从 , 变成 ;。我该如何处理由于在不同程序中打开而可能保存的各种分隔符,比如在 Windows 的 Excel、Mac 的 Excel、Mac 的 Open Office、Linux 的 Open Office 等等。

另一个问题是,当用户试图将数据复制粘贴到提供的模板中时,情况就变得非常糟糕。

更新
我现在正在使用 Sniffer 类,正如下面某个回答中提到的,但这仍然不是万无一失的。

更新后的代码片段

def bulk_import_residents(condo, resident_file):

    """
    COL 1       COL 2       COL 3           COL 4           COL 5        
    first_name  last_name   contact_number  unit_number     block_number

    """

    file_path = resident_file.file.path
    csvfile = open(file_path, 'rb')
    dialect =  csv.Sniffer().sniff(csvfile.read(1024))
    csvfile.seek(0)
    reader = csv.reader(csvfile, dialect)
    headerline = reader.next()

    for row in reader:
        try:
            data = ResidentImportData()
            data.condo = condo
            data.file = resident_file
            data.first_name = row[0]
            data.last_name = row[1] 
            data.contact_number = row[2]
            data.unit_number = row[3]
            data.block_number = row[4]
            data.save()
        except Exception, e:
            print '{0}'.format(e)
            raise Http404('Wrong template format')

9 个回答

1

我刚刚发现了sniffer类。

csvfile = open("example.csv", "rb")
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
# ... process CSV file contents here ...
2

CSV其实是一种没有固定格式的文件。Sniffer这个类并不是完全可靠的,因为实际上要100%准确地识别所有不同的CSV格式是不可能的。

我觉得你可能需要依赖Sniffer,因为它在90%的情况下都能正常工作。同时,你还需要处理那些不符合格式的输入文件,分析它们,然后对Sniffer进行扩展,以便能够识别这些特殊情况。

2

我完全同意nfirvine的看法(CSV根本算不上格式)——虽然说得有点重,但确实是个很简单的格式。它的规则很松散。如果你使用CSV,常常会遇到问题,听起来你已经有这种体验了。

我也同意Mike Bynum的建议——可以考虑用XML这样的格式。

不过我明白,即使有更好的方法,有时候我们还是得选择实际可行的方案。可能因为各种原因你不得不坚持使用CSV格式……所以这里有两条路可以走。

第一条路:CSV

我现在就是走这条路。我的用户每天都会更新数据(几千条记录)。考虑到更新的频率和数量,我真希望当初选择了第二条路:处理大量数据或更新时,良好的数据验证能节省很多时间。

话虽如此,如果你不得不使用CSV,我建议你可以这样做:

  • 给用户提供一个清晰的CSV定义,也就是RFC 4180。确保客户明白你希望他们的文件包含什么:
    • 一个标题行。
    • 用逗号分隔。
    • 任何包含逗号的数据都要用引号括起来。
  • 除了定义,还要给用户一个CSV的示例(听起来你已经做到了,挺好!)。解释一下,如果CSV文件不符合你的数据定义,你就无法处理。
  • 在导入之前,确保文本文件的类型是你所期待的——可以查看如何转换Unix/Windows格式
  • 在你的CSV解析器中,采用快速失败的方法,确保有机制通知用户当CSV文件不符合你预期的标准时。尽量提供详细的信息(提供异常的细节……如果不是为了他们,至少也是为了你自己)。
  • 你提到的某个客户文件的问题,说明你可能需要给客户一些建议,告诉他们哪些编辑器是你知道可以正常工作的。Excel应该可以,或者Open Office。我建议使用电子表格应用,因为它们在导出CSV时能很好地处理引号等问题。

并不是说你不能支持一些特殊情况,但一般来说——你要尽量避免这些情况,避免意外导入格式不正确的数据。

第二条路:XML

我建议你可以这样做:

  • 用模式定义(XSD)来明确用户需要导入的数据。我喜欢随身带着w3c的定义。不过也有不错的教程可以帮助你编写自己的XSD定义。

  • 给用户一个示例XML文件,让他们填写,并建议使用某个编辑器。有一些优秀的商业软件,还有一些合理的免费软件

  • 你可以读取用户的XML文件,确保它通过验证,这样就可以放心使用。用户也可以在发送给你之前进行验证

撰写回答