【问题标题】:Getting empty sqlite DB and "(sqlite3.OperationalError) no such table:..:" when trying to add item尝试添加项目时获取空的sqlite DB和“(sqlite3.OperationalError)没有这样的表:..:”
【发布时间】:2018-10-25 09:45:09
【问题描述】:

我写了一个通用的dbhandler模​​块,可以纠缠数据容器,上传到mySQL数据库,独立于DB结构。现在我想添加一个默认值或将数据推送到 sqlite DB 的可能性。从结构上讲,这与question 有关。包长这样:

dbhandler\
    dbhandler.py
    models\
       meta.py
       default\   
          default_DB_map.py 
          default_DB.cfg 

default.cfg 是描述 dbhandler 脚本的数据库的配置文件。 default_DB_map.py 包含数据库的每个表的映射,它继承自 BASE:

from sqlalchemy import BigInteger, Column, Integer, String, Float, DateTime
from sqlalchemy import Date, Enum
from ..meta import BASE

class db_info(BASE):
    __tablename__ = "info"

    id = Column(Integer, primary_key=True)
    name = Column(String)
    project = Column(String)
    manufacturer = Column(String)
    ...

class db_probe(BASE):
    __tablename__ = "probe"

    probeid = Column(Integer, primary_key=True)
    id = Column(Integer)
    paraX = Column(String)
    ...

在 meta.py 我初始化 declarative_base 对象:

from sqlalchemy.ext.declarative import declarative_base
BASE = declarative_base()

最后,我在 dbhandler.py 中导入 BASE 并创建引擎和会话:

"DBHandler module"
...
import sqlalchemy
from sqlalchemy.orm import sessionmaker
from models import meta #pylint: disable=E0401

....
class DBHandler(object):
     """Database handling

     Methods:
        - get_dict:         returns table row
        - add_item:         adds dict to DB table
        - get_table_keys:   gets list of all DB table keys
        - get_values:       returns all values of key in DB table
        - check_for_value:  checks if value is in DB table or not
        - upload:           uploads data container to DB
        - get_dbt:          returns DBTable object
    """
    def __init__(self, db_cfg=None):
        """Load credentials, DB structure and name of DB map from cfg file,
           create DB session. Create DBTable object to get table names of DB
           from cfg file, import table classes and get name of primary keys.

        Args:
            - db_cfg (yaml) : contains infos about DB structure and location 
                              of DB credentials.
        Misc:
            - cred = {"host"      : "...",
                      "database"  : "...",
                      "user"      : "...",
                      "passwd"    : "..."}
        """
        ...
        db_cfg = self.load_cfg(db_cfg)

        if db_cfg["engine"] == "sqlite":
            engine = sqlalchemy.create_engine("sqlite:///mySQlite.db")
            meta.BASE.metadata.create_all(engine)
            session = sessionmaker(bind=engine)
            self.session = session()
        elif db_cfg["engine"] == "mysql+mysqlconnector":
            cred = self.load_cred(db_cfg["credentials"])
            engine = sqlalchemy.create_engine(db_cfg["engine"]
                                              + "://"
                                              + cred["user"] + ":"
                                              + cred["passwd"] + "@"
                                              + cred["host"] + ":"
                                              + "3306" + "/"
                                              + cred["database"])
            session = sessionmaker(bind=engine)
            self.session = session()
        else:
            self.log.warning("Unkown engine in DB cfg...")
        
        # here I'm importing the table classes stated in the config file
        self.dbt = DBTable(map_file=db_cfg["map"],
                           table_dict=db_cfg["tables"],
                           cr_dict=db_cfg["cross-reference"])

我显然在if db_cfg["engine"] == "sqlite": 段落中做错了,但我不知道是什么。

脚本在 mySQL 引擎上运行良好。当我初始化处理程序对象时,我得到一个空的mySQLite.db 文件。 在该会话中添加一些东西会产生:

(sqlite3.OperationalError) no such table: info.... 

但是,我可以在表对象上使用类似“sqlalchemy.inspect”的东西而不会出现任何错误。所以我手头有正确的表对象,但它们不知何故没有连接到基础?

【问题讨论】:

    标签: mysql database python-3.x sqlite sqlalchemy


    【解决方案1】:

    对于 SQLite,显然需要在创建数据库之前导入表类。

        # here I'm importing the table classes stated in the config file
        self.dbt = DBTable(map_file=db_cfg["map"],
                           table_dict=db_cfg["tables"],
                           cr_dict=db_cfg["cross-reference"])
    

    (通过 pydoc.locate btw 完成)必须在

    之前完成
            engine = sqlalchemy.create_engine("sqlite:///mySQlite.db")
            meta.BASE.metadata.create_all(engine)
            session = sessionmaker(bind=engine)
            self.session = session()
    

    被调用。我认为这并不重要,因为我一开始就导入了 BASE,而且在使用不同的引擎时它工作得很好。

    【讨论】:

    • 你的推理是错误的。无论使用何种方言,这些表都必须已构建并存在于MetaData 中。您的 MySQL 代码要么恰好在调用 create_all() 之前运行了 Table 和声明性类定义,要么您之前已经创建了表。
    猜你喜欢
    • 1970-01-01
    • 2022-01-17
    • 2019-09-10
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 2016-02-20
    • 2018-08-18
    相关资源
    最近更新 更多