Python写入CSV格式异常:内容换行与多余引号问题排查
Python测验程序CSV写入问题排查与修复方案
问题情况
你开发的Python测验程序需要把用户添加的试题(question、answer、questiontype、subject)写入CSV同一行,比如期望输出:
when did WWII start,1939,multiple choice,History
但实际写入时内容被拆成多行,还出现多余引号,导致CSV格式混乱。
问题根源
- Text控件的换行符残留:tkinter的
Text.get("1.0", "end")会把输入内容末尾的换行符(\n)也取出来,csv模块遇到字段里的换行符时,会自动用引号包裹该字段,同时换行符会让内容拆成多行。 - 重复添加"New Subject":
openAdding函数里把UniqueSubject.append("New Subject")放在了循环内部,导致每次读取CSV行都会添加一次,下拉菜单里会出现多个重复的"New Subject"选项。 - 按钮拼写错误:else分支里的按钮文本写成了"Sumbit",应该是"Submit"。
修正方案
- 去除Text输入的末尾换行:把
Question.get("1.0", "end")改成Question.get("1.0", "end-1c"),end-1c表示取到最后一个字符之前,自动去掉末尾的换行符;Answer控件同理。 - 调整"New Subject"添加位置:把
UniqueSubject.append("New Subject")移到循环外面,确保下拉菜单里只出现一次"New Subject"。 - 修正按钮拼写错误:把"Sumbit"改成"Submit"。
完整修正代码
import csv import tkinter as tk root = tk.Tk() # 假设root已在其他地方定义,此处补全必要初始化 def SaveToCsv(subject, question, answer, questiontype): with open(r"BankOfQuestions.csv", "a", newline='', encoding='utf-8') as Bank: writer = csv.writer(Bank, delimiter=',') writer.writerow([question, answer, questiontype, subject]) def AddNewQuestion(subject): window = tk.Toplevel(root) window.title(f"Add a new question for {subject}") if subject == "New Subject": Label1 = tk.Label(window, text="Enter name of subject") Label1.pack() SubjectTitle = tk.StringVar() NameOfSubject = tk.Entry(window, textvariable=SubjectTitle, font=("Ariel", 10)) NameOfSubject.pack() Label2= tk.Label(window, text="Enter the question", pady=12) Label2.pack() Question = tk.Text(window, font=("Ariel", 10), height=9) Question.pack() Label3 = tk.Label(window, text= "Enter the answer", pady=12) Label3.pack() Answer= tk.Text(window, font=("Ariel", 10), height=9) Answer.pack() qtypes = ["multiple choice", "written"] QuestionType = tk.StringVar() QuestionType.set("Select question type") drop = tk.OptionMenu(window, QuestionType, *qtypes) drop.pack(pady=12) # 去除Text输入末尾的换行符 Submit = tk.Button(window, text="Submit", command= lambda: SaveToCsv(SubjectTitle.get(), Question.get("1.0", "end-1c"), Answer.get("1.0", "end-1c"), QuestionType.get())) Submit.pack() else: Label2= tk.Label(window, text="Enter the question", pady=12) Label2.pack() Question = tk.Text(window, font=("Ariel", 10), height=9) Question.pack() Label3 = tk.Label(window, text= "Enter the answer", pady=12) Label3.pack() Answer= tk.Text(window,font=("Ariel", 10), height=9) Answer.pack() qtypes = ["multiple choice", "written"] QuestionType = tk.StringVar() QuestionType.set("Select question type") drop = tk.OptionMenu(window, QuestionType, *qtypes) drop.pack(pady=12) # 修正按钮拼写+去除换行符 Submit = tk.Button(window, text="Submit", command= lambda :SaveToCsv(subject, Question.get("1.0","end-1c"), Answer.get("1.0","end-1c"), QuestionType.get())) Submit.pack() def openAdding(): window = tk.Toplevel(root) window.title("Add a question") UniqueSubject = [] try: with open("BankOfQuestions.csv", "r") as Bank: Stuff = csv.reader(Bank) for line in Stuff: # 处理空行,避免索引越界 if len(line) <4: continue subject = line[3] if subject == "Subject" or subject == "" or subject in UniqueSubject: pass else: UniqueSubject.append(subject) # 把New Subject移到循环外,只添加一次 UniqueSubject.append("New Subject") except FileNotFoundError: # 首次运行文件不存在时,直接添加New Subject UniqueSubject.append("New Subject") menu = tk.StringVar() menu.set("Pick a Subject") drop = tk.OptionMenu(window, menu, *UniqueSubject, command= lambda x: AddNewQuestion(menu.get())) drop.pack() Quitter = tk.Button(window, text="Quit", font=("Ariel", 20), command=window.destroy) Quitter.pack() # root.mainloop() # 按需启用主窗口循环
额外优化
新增了try-except处理CSV文件不存在的情况,避免首次运行报错;同时处理CSV内的空行,防止索引越界问题。
内容的提问来源于stack exchange,提问作者Herwin
相关产品推荐
相关产品推荐

