从CSV导入映射Python SQLAlchemy中的类列标题
我在类中设置列名,如下所示:从CSV导入映射Python SQLAlchemy中的类列标题,python,sqlite,csv,sqlalchemy,Python,Sqlite,Csv,Sqlalchemy,我在类中设置列名,如下所示: class Stat1(Base): __tablename__ = 'stat1' __table_args__ = {'sqlite_autoincrement': True} id = Column(VARCHAR, primary_key=True, nullable=False) Date_and_Time = Column(VARCHAR) IP_Address = Column(VARCHAR) Visitor_Label = Column(VARC
class Stat1(Base):
__tablename__ = 'stat1'
__table_args__ = {'sqlite_autoincrement': True}
id = Column(VARCHAR, primary_key=True, nullable=False)
Date_and_Time = Column(VARCHAR)
IP_Address = Column(VARCHAR)
Visitor_Label = Column(VARCHAR)
Browser = Column(VARCHAR)
Version = Column(VARCHAR)
csv文件在列名中不使用下划线。它是从internet下载的csv文件。例如,当我导入列名时,像“Date_和_Time”这样的标题被导入为“Date和Time”
我曾假设(这是错误的,对吗?)CSV的列名会映射到我设置的类列标题,但事实并非如此,因此查询无法正常运行。我收到的信息如下:
sqlalchemy.exc.OperationalError:(sqlite3.OperationalError)没有这样的错误
列:stat1.Date_和时间[SQL:'选择stat1.id作为stat1_id,
stat1.“日期和时间”为“stat1日期和时间”,stat1.“IP地址”为
“stat1\U IP\U地址”等
是否有一种方法可以自动映射这些内容以使查询成功?或者有一种方法可以自动更改CSV的列标题以在列标题中插入下划线以与类中定义的列相匹配?有几种不同的方法可以实现这一点: 实现您自己的反序列化逻辑 这意味着读取CSV文件并将其列映射到
Base
model类的属性的过程是手动完成的(如您的问题所示),然后您使用自己的自定义代码读取/映射CSV
我认为,在这种情况下,在模型类属性(Stat1.Date_和_Time
)中使用下划线,而在CSV头(,“Date and Time”,…
)中不使用下划线会使代码复杂化一点。但是,根据您实现映射代码的方式,您可以将列设置为使用一个模型属性名称(Stat1.日期和时间
)
和不同的数据库列名(例如,将Stat1.Date\u和_Time
映射到数据库列“Date and Time”
)。要完成此操作,需要传递name
参数,如下所示:
class Stat1(Base):
__tablename__ = 'stat1'
__table_args__ = { 'sqlite_autoincrement': True }
id = Column(name = 'id', type_ = VARCHAR, primary_key = True, nullable = False)
Date_and_Time = Column(name = 'Date and Time', type_ = VARCHAR)
IP_Address = Column(name = 'IP Address', type_ = VARCHAR)
# etc.
现在,当您从CSV文件中读取记录时,需要将它们加载到Stat1
类中相应的模型属性中。伪代码示例如下:
id, date_and_time, ip_address = read_csv_record(csv_record)
# Let's assume the "read_csv_record()" function reads your CSV record and returns
# the appropriate value for `id`, `Date_And_Time`, and `IP_Address`
my_record = Stat1(id = id,
Date_And_Time = date_and_time,
ip_address
# etc.)
这里的诀窍是实现read\u csv\u record()
函数,以便它读取并返回模型属性的列值,然后您可以将它们适当地传递给Stat1()
构造函数
使用SQLAthanor
实现您自己的反序列化解决方案的一个(我认为更容易)替代方案是使用类似于的库(完全公开:我是该库的作者,所以我有点偏见)。使用SQLAthanor,您可以:
以编程方式创建您的Stat
模型类:
from sqlathanor import generate_model_from_csv
Stat1 = generate_model_from_csv('your_csv_file.csv',
'stat1',
primary_key = 'id')
但是,请注意,如果列标题名称不是ANSI SQL标准列名(例如,如果它们包含空格),则可能会产生错误
定义模型,然后从CSV创建实例
要做到这一点,您将以与上面类似的方式定义您的模型:
from sqlathanor import BaseModel
class Stat1(BaseModel):
__tablename__ = 'stat1'
__table_args__ = { 'sqlite_autoincrement': True }
id = Column(name = 'id', type_ = VARCHAR, primary_key = True, nullable = False, supports_csv = True, csv_sequence = 1)
Date_and_Time = Column(name = 'Date and Time', type_ = VARCHAR, supports_csv = True, csv_sequence = 2)
IP_Address = Column(name = 'IP Address', type_ = VARCHAR, supports_csv = True, csv_sequence = 3)
# etc.
supports_csv
参数告诉您的Stat1
类,模型属性Stat1.id
可以从csv反序列化(并序列化为csv),并且csv_sequence
参数指示它将始终是csv记录中的第一列
现在,您可以通过将CSV记录传递给Stat1来创建一个新的Stat1
实例(数据库中的记录)。new\u from\u CSV()
:
就是这样!现在,您的my_record
变量将包含CSV记录的对象表示形式,您可以在选择时将其提交到数据库。因为可以通过多种方式构造CSV文件(使用不同的分隔符、包装策略等)有大量的配置参数可以提供给.new\u from\u csv()
,但您可以在此处找到所有这些参数:
SQLAthanor是一个非常强大的库,用于将数据移入/移出CSV和SQLAlchemy,因此我强烈建议您查看文档。以下是重要的链接:
希望这有帮助!我一定会查看该库。从所有迹象来看,它可能对其他方面也有帮助。我的目标是使用Selenium每天以编程方式下载一次该文件,将其保存到目录中,然后对脚本进行CRON以上载CSV文件以填充数据库。然后通过计算检索我需要的数据因此,我试图尽可能避免手动操作。然而,一旦我第一次正确设置了所有内容,那么随后的尝试可能就不需要操作了。
# let's assume you have loaded a single CSV record into a variable "csv_record"
my_record = Stat1.new_from_csv(csv_record)