将CSV导入SQLite3时遇TypeError:空字符串为Tasks无效关键字参数
问题
将CSV文件导入SQLite3数据库时触发错误:TypeError: '' is an invalid keyword argument for Tasks。使用Python的ORM库SQLAlchemy,通过declarative_base()定义了Tasks映射类,尝试将csv.DictReader读取的行数据转换为Tasks实例时出现该问题,相关代码及报错堆栈如下:
import csv from dateutil.parser import parse from sqlalchemy import Column, Date, Float, Integer, String, create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker engine = create_engine("sqlite:///tasks.sqlite3", echo=True) Base = declarative_base() """ Now we will define the user class """ class Tasks(Base): """ Table arguments other than the name, metadata, and mapped Column arguments are specified using the __table_args__ class attribute. The __table_args__ class attribute in this case will be assigned a string value. https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/table_config.html """ # Tasks_ID, Description, User_ID __tablename__ = "tasks" # This is User class database table name attribute # task_id Tasks_ID = Column(Integer, primary_key = True) # This the primary key attribute # description Description = Column(String(30)) # User_ID User_ID = Column(Integer) # Sprint_ID Sprint_ID = Column(Integer) # Team_ID Team_ID = Column(Integer) # Story_Points Story_Points = Column(Integer, nullable=True) Current_State = Column(String(30)) # Sprint_ID , Team_ID, Story_Points, Current_State Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) def parse_none(dt): """Trys to parse a string date and returns None if unable to.""" try: return parse(dt) except: return None def prepare_listing(row): """Takes a row from CSV file and returns a Listing object from it.""" row["Story_Points"] = parse_none(row["Story_Points"]) return Tasks(**row) with open("new_tasks.csv", encoding="utf-8", newline="") as csv_file: csvreader = csv.DictReader(csv_file, quotechar='"') listings = [prepare_listing(row) for row in csvreader] session = Session() session.add_all(listings) session.commit()
报错堆栈:
TypeError Traceback (most recent call last) /Users/shawnyang/Downloads/test/test2.ipynb Cell 1 in <cell line: 85>() 85 with open("new_tasks.csv", encoding="utf-8", newline="") as csv_file: 86 csvreader = csv.DictReader(csv_file, quotechar='"') ---> 88 listings = [prepare_listing(row) for row in csvreader] 90 session = Session() 91 session.add_all(listings) /Users/shawnyang/Downloads/test/test2.ipynb Cell 1 in <listcomp>(.0) 85 with open("new_tasks.csv", encoding="utf-8", newline="") as csv_file: 86 csvreader = csv.DictReader(csv_file, quotechar='"') ---> 88 listings = [prepare_listing(row) for row in csvreader] 90 session = Session() 91 session.add_all(listings) /Users/shawnyang/Downloads/test/test2.ipynb Cell 1 in prepare_listing(row) 78 """Takes a row from CSV file and returns a Listing object from it.""" 80 row["Story_Points"] = parse_none(row["Story_Points"]) ---> 81 return Tasks(**row) File <string>:4, in __init__(self, **kwargs) File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/sqlalchemy/orm/state.py:481, in InstanceState._initialize_instance(*mixed, **kwargs) 479 return manager.original_init(*mixed[1:], **kwargs) ... 1164 "%r is an invalid keyword argument for %s" % (k, cls_.__name__) 1165 ) 1166 setattr(self, k, kwargs[k]) TypeError: '' is an invalid keyword argument for Tasks
解决方案
错误根源
报错提示空字符串''是Tasks类的无效参数,说明CSV文件的表头存在空列名,或者csv.DictReader解析时生成了空字符串作为键名,而Tasks类没有对应的属性,实例化时就会触发错误。
修复步骤
清理CSV表头
打开new_tasks.csv文件,检查第一行表头,删除其中的空列名,确保所有表头和Tasks类的属性名完全匹配(注意大小写,比如Tasks_ID、Description等)。在代码中过滤无效键
如果无法修改CSV文件,可在prepare_listing函数中过滤掉行数据里的空键和Tasks类未定义的键:def prepare_listing(row): """将CSV行数据转换为Tasks实例""" # 定义Tasks类的有效属性集合 valid_attrs = {'Tasks_ID', 'Description', 'User_ID', 'Sprint_ID', 'Team_ID', 'Story_Points', 'Current_State'} # 过滤掉空键和无效键 cleaned_row = {k: v for k, v in row.items() if k in valid_attrs and k.strip() != ''} # 处理Story_Points字段 if 'Story_Points' in cleaned_row: cleaned_row["Story_Points"] = parse_none(cleaned_row["Story_Points"]) return Tasks(**cleaned_row)修正
parse_none函数逻辑
原函数用dateutil.parser.parse处理Story_Points(整数类型)是错误的,应该改为转换整数的逻辑:def parse_none(value): """尝试将字符串转为整数,失败则返回None""" try: return int(value.strip()) if value.strip() else None except (ValueError, TypeError): return None
内容的提问来源于stack exchange,提问作者Born2Student
相关产品推荐
相关产品推荐

