使用Python/Django提取CSV行时遇索引错误等问题求助
问题描述
我正尝试使用Python/Django提取CSV文件中的特定行,CSV内容格式如下:
POS,Transaction id,Product,Quantity,Customer,Date 1,E100,TV,1,Test Customer,2022-09-19 2,E100,Laptop,3,Test Customer,2022-09-20 3,E200,TV,1,Test Customer,2022-09-21 4,E300,Smartphone,2,Test Customer,2022-09-22 5,E300,Laptop,5,New Customer,2022-09-23 6,E300,TV,1,New Customer,2022-09-23 7,E400,TV,2,ABC,2022-09-24 8,E500,Smartwatch,4,ABC,2022-09-25
编写的代码如下:
def csv_upload_view(request): print('file is being uploaded') if request.method == 'POST': csv_file = request.FILES.get('file') obj = CSV.objects.create(file_name=csv_file) with open(obj.file_name.path, 'r') as f: reader = csv.reader(f) reader.__next__() for row in reader: data = "".join(row) data = data.split(";") #data.pop() print(data[0], type(data)) transaction_id = data[0] product = data[1] quantity = int(data[2]) customer = data[3] date = parse_date(data[4])
控制台输出如下:
Quit the server with CONTROL-C. [22/Sep/2022 15:16:28] "GET /reports/from-file/ HTTP/1.1" 200 11719 file is being uploaded 1E100TV1Test Customer2022-09-19 <class 'list'>
行内容被拼接在一起,若用空格join则行内容被空格分隔。我希望通过指定方式访问行数据,但总是出现IndexError: list index out of range。尝试用data.replace(" ",";"),又出现ValueError: invalid literal for int() with base 10: 'E',且数据类型变为字符串。请问我忽略了什么?
问题分析与解决
核心问题是你完全误用了csv.reader的工作逻辑,多做了画蛇添足的拼接和分割操作,具体问题点和修复方案如下:
csv.reader已经帮你完成了行分割csv.reader读取CSV文件时,会自动按照逗号(CSV默认分隔符)把每行拆分成列表。比如第一行数据会直接被处理成['1', 'E100', 'TV', '1', 'Test Customer', '2022-09-19'],你不需要再用"".join(row)把它们拼起来——这直接破坏了已经分割好的结构,而你的CSV里根本没有分号,后续用split(";")自然只能得到一个元素的列表,访问data[1]、data[2]这类索引时必然报IndexError。修复后的代码示例
直接使用csv.reader返回的row列表即可,无需额外处理:
def csv_upload_view(request): print('file is being uploaded') if request.method == 'POST': csv_file = request.FILES.get('file') obj = CSV.objects.create(file_name=csv_file) with open(obj.file_name.path, 'r', encoding='utf-8') as f: reader = csv.reader(f) next(reader) # 跳过表头,用next()比__next__()更符合Python规范 for row in reader: # row已经是分割好的字段列表,直接按索引取值 pos = row[0] transaction_id = row[1] product = row[2] quantity = int(row[3]) customer = row[4] date = parse_date(row[5]) # 这里可以添加保存到数据库等后续逻辑 print(f"交易ID: {transaction_id}, 商品: {product}")
- 额外注意事项
- 如果你的CSV文件用的不是逗号分隔符,需要在创建
csv.reader时指定delimiter参数,比如csv.reader(f, delimiter=';'),但你的示例CSV用的是逗号,所以不需要。 - 打开文件时建议指定编码(如
utf-8),避免中文乱码问题。 next(reader)用于跳过表头行,这部分逻辑是对的,但用内置函数next()比直接调用reader.__next__()更规范。
内容的提问来源于stack exchange,提问作者sloth
相关产品推荐
相关产品推荐

