【问题标题】:SQLAlchemy: Class values not populated in SQLite table after converting csv to dictionariesSQLAlchemy:将 csv 转换为字典后,类值未填充到 SQLite 表中
【发布时间】:2018-10-22 09:47:04
【问题描述】:

我创建了一个 SQLite 数据库和类,声明了我的列,并尝试使用我在 Pandas 中导入并转换为字典的 csv 文件中的数据填充它。

然后我使用 SQLAlchemy 中的 MetaData 来反映这些表,然后我将对“测量”和“站”表的引用保存到它们各自的表变量中。最后,我将数据插入表中,但是,当我获取插入数据的前五个值(以确保插入有效)时,我什么也得不到。我很困惑,我错过了什么或做错了什么?

# Dependencies and boilerplate
import sqlalchemy
from sqlalchemy import Column, Float, Integer, String, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, inspect, func, MetaData

engine = create_engine("sqlite:///Resources/hawaii.sqlite")

conn = engine.connect()

Base = declarative_base()

class Measurement(Base):
    __tablename__ = "measurement"

    id = Column(Integer, primary_key=True)
    station = Column(Text)
    date = Column(Text)
    prcp = Column(Float) 
    tobs = Column(Integer)

    def __repr__(self):
        return f"id={self.id}, name={self.name}"


class Station(Base):
    __tablename__ = "station"

    id = Column(Integer, primary_key=True)
    station = Column(Text)
    name = Column(Text)
    latitude = Column(Float)
    longitude = Column(Float)
    elevation = Column(Float)

    def __repr__(self):
        return f"id={self.id}, name={self.name}"

# Create a "Metadata" Layer That Abstracts our SQL Database
# ----------------------------------
Base.metadata.tables # Right now, this table only exists in python and not in the actual database

Base.metadata.create_all(engine) # Create the 2 tables within the database

# csv to df to dict.
cm_df = "resources/clean_measurements.csv"
cs_df = "resources/clean_stations.csv"
cm_df = pd.read_csv(cm_df)
cs_df = pd.read_csv(cs_df)

cm_df=cm_df.drop(['Unnamed: 0'], axis=1).reset_index(drop=True)
cs_df=cs_df.drop(['Unnamed: 0'], axis=1).reset_index(drop=True)

cm_dic = cm_df.to_dict(orient='records')
cs_dic = cs_df.to_dict(orient='records')

# Use MetaData from SQLAlchemy to reflect the tables
metadata = MetaData(bind=engine)
metadata.reflect()

# Populate SQLITE Table for Measurement_df
m_table = sqlalchemy.Table('measurement', metadata, autoload=True)
conn.execute(m_table.delete())
conn.execute(m_table.insert(), cm_dic)

# Populate SQLITE Table for stations_df
s_table= sqlalchemy.Table('station', metadata, autoload=True)
conn.execute(s_table.delete())
conn.execute(s_table.insert(), cs_dic)

conn.execute("select * from measurement Limit 5").fetchall()
>>> [(1,), (2,), (3,), (4,), (5,)]
conn.execute("select * from station limit 5").fetchall()
>>> [(1,), (2,), (3,), (4,), (5,)]

【问题讨论】:

  • 出于好奇,为什么您首先使用声明式来定义您的模型等,然后创建完全独立的元数据并反映(几乎)相同的信息?
  • 这是在学习 SQLAlchemy 的上下文中,这里的冗余是为了演示 SQL 的表是如何通过手动声明表和关联列来构造的。

标签: sql pandas sqlite sqlalchemy


【解决方案1】:

您的操作查询可能没有提交。根据 ORM 上下文中的 SQLAlchemy docs

“自动提交”功能仅在没有事务时有效 否则被宣布。这意味着该功能通常不被使用 使用 ORM,因为默认情况下 Session 对象总是维护一个 正在进行的交易。

考虑运行处理提交和回滚的transactions in a context manager

...

with engine.begin() as cn:
   cn.execute(m_table.delete())
   cn.execute(m_table.insert(), cm_dic)

...

with engine.begin() as cn:
   cn.execute(s_table.delete())
   cn.execute(s_table.insert(), cs_dic)

...
engine.execute("select * from measurement Limit 5")

engine.execute("select * from station limit 5")

【讨论】:

  • 谢谢 M. Parfait!我尝试了您的解决方案,但输出是相同的。我确实解决了我的问题:我在我的目录中手动删除了我的 SQLite 数据库,清除了我的输出并重新运行了我的脚本......我相信你说我的查询没有提交是对的......我只是不知道为什么确切地说...抱歉,我对 SQLAlchemy 和 ORM 的了解不够深入。
猜你喜欢
  • 2014-04-24
  • 2017-11-08
  • 2020-01-03
  • 2014-09-16
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 2018-12-09
相关资源
最近更新 更多