上传固定格式的CSV文件
我有一个 .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 个回答
我刚刚发现了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 ...
CSV其实是一种没有固定格式的文件。Sniffer
这个类并不是完全可靠的,因为实际上要100%准确地识别所有不同的CSV格式是不可能的。
我觉得你可能需要依赖Sniffer
,因为它在90%的情况下都能正常工作。同时,你还需要处理那些不符合格式的输入文件,分析它们,然后对Sniffer
进行扩展,以便能够识别这些特殊情况。
我完全同意nfirvine的看法(CSV根本算不上格式)——虽然说得有点重,但确实是个很简单的格式。它的规则很松散。如果你使用CSV,常常会遇到问题,听起来你已经有这种体验了。
我也同意Mike Bynum的建议——可以考虑用XML这样的格式。
不过我明白,即使有更好的方法,有时候我们还是得选择实际可行的方案。可能因为各种原因你不得不坚持使用CSV格式……所以这里有两条路可以走。
第一条路:CSV
我现在就是走这条路。我的用户每天都会更新数据(几千条记录)。考虑到更新的频率和数量,我真希望当初选择了第二条路:处理大量数据或更新时,良好的数据验证能节省很多时间。
话虽如此,如果你不得不使用CSV,我建议你可以这样做:
- 给用户提供一个清晰的CSV定义,也就是RFC 4180。确保客户明白你希望他们的文件包含什么:
- 一个标题行。
- 用逗号分隔。
- 任何包含逗号的数据都要用引号括起来。
- 除了定义,还要给用户一个CSV的示例(听起来你已经做到了,挺好!)。解释一下,如果CSV文件不符合你的数据定义,你就无法处理。
- 在导入之前,确保文本文件的类型是你所期待的——可以查看如何转换Unix/Windows格式。
- 在你的CSV解析器中,采用快速失败的方法,确保有机制通知用户当CSV文件不符合你预期的标准时。尽量提供详细的信息(提供异常的细节……如果不是为了他们,至少也是为了你自己)。
- 你提到的某个客户文件的问题,说明你可能需要给客户一些建议,告诉他们哪些编辑器是你知道可以正常工作的。Excel应该可以,或者Open Office。我建议使用电子表格应用,因为它们在导出CSV时能很好地处理引号等问题。
并不是说你不能支持一些特殊情况,但一般来说——你要尽量避免这些情况,避免意外导入格式不正确的数据。
第二条路:XML
我建议你可以这样做: