Python 使用动态表格生成完全刷新SQLAlchemy

Python 使用动态表格生成完全刷新SQLAlchemy,python,sqlalchemy,Python,Sqlalchemy,我需要在for循环中的不同位置创建许多类似的数据库。在循环的开始,我在磁盘上创建了一个新的path\u sql\u db引擎 engine = sa.create_engine("sqlite:///{}".format(path_sql_db), echo=0, listeners=[util_sa.ForeignKeysListener()]) Session = sa.orm.sessionmaker(bind=engine) session = Session()

我需要在for循环中的不同位置创建许多类似的数据库。在循环的开始,我在磁盘上创建了一个新的
path\u sql\u db
引擎

    engine = sa.create_engine("sqlite:///{}".format(path_sql_db), echo=0, listeners=[util_sa.ForeignKeysListener()])
    Session = sa.orm.sessionmaker(bind=engine)
    session = Session()
然后,我让我在几个模块中的表继承自外部模块中定义的DB_Base

from sqlalchemy.ext.declarative import declarative_base
DB_Base = declarative_base()
问题是,在for循环的下一次迭代中,我无法创建我的表,因为它们仍然存在于某个地方

InvalidRequestError: Table 'vector_var01' is already defined for this MetaData instance.  
Specify 'extend_existing=True' to redefine options and columns on an existing Table object.
我已尝试从引擎中删除元数据

meta = sa.MetaData(bind = engine)
meta.reflect()
meta.drop_all()
session.close()
也从基地出发,

DB_Base.metadata.bind = engine
DB_Base.metadata.reflect()
DB_Base.metadata.drop_all()
没有成功,我仍然在黑暗中游荡

错误引用的是哪个元数据实例?如何完全重置数据库代码的状态

编辑

好的,我找到了问题所在。我正在尝试动态生成ORM表。我正在研究优化例程,并将设计空间变量存储在它们自己的表中,每个变量的可能值一行

导致错误的最小示例

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()

class Foo(Base):
    __tablename__ = 'foo'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))

def generate_variable_table_class(name):
    """This is a helper function which dynamically creates a new ORM enabled class
    The table will hold the individual values of each variable
    Individual values are stored as a string
    """

    class NewTable( Base ):
        __tablename__ = "vector_{}".format(name)
        id = Column(Integer, primary_key=True)
        value = Column(String(16), nullable=False, unique=True)
        def __init__(self,value):
            self.value = str(value)

        def __str__(self):
            return self.value

        def __repr__(self):
            return self.value    


    NewTable.__name__ = "vector_ORM_{}".format(name)

    return NewTable


if __name__ == "__main__":

    for name in 'asfd', 'jkl', 'xyz':
        print("For loop: ",name)
        engine = create_engine(r'sqlite:///c:\testdelete\{}.sql'.format(name))
        Base.metadata.create_all(engine)
        Session = sessionmaker(bind=engine)
        session = Session()

        bunch_o_foos = [Foo(name = i) for i in range(10)]
        session.add_all(bunch_o_foos)
        session.commit()
        for foo in bunch_o_foos:
            print(foo.id)


        variables = [generate_variable_table_class(i) for i in range(10)]
这实际上和这个问题是一样的。这不可能吗

作为一个简单的例子:

从sqlalchemy导入*
从sqlalchemy.ext.declarative导入声明性基础
Base=声明性_Base()
Foo类(基本类):
__tablename_uuu='foo'
id=列(整数,主键=True)
名称=列(字符串(50))
对于“asfd”、“jkl”、“xyz”中的名称:
engine=create_engine('sqlite://{}'。格式(名称))
Base.metadata.create_all(引擎)
运行良好
drop\u all
表示删除表,可能不是您想要的。一旦您使用了
bind
,您就将元数据对象绑定到了特定的引擎。尽管:

Base.metadata.bind = engine
Base.metadata.create_all()
也适用于最小示例

编辑

根据示例案例,出现错误是因为您试图使用相同的
Base
子类定义具有相同表名(例如vector_0)的类,该子类附加了一个
MetaData
对象,每个表名只能有一个

  • 在新的简单示例中,每个数据库的表之间没有区别,因此您应该将对
    generate\u variable\u table\u class
    的调用移出主循环,只调用一次

  • 如果您有每个数据库的行为,那么每次都可以使用一个新的
    Base
    (也就是说,将
    Foo
    移动到一个函数中!)(另外,对
    generate\u variable\u table\u class
    的调用应该在
    create\u all
    之上,而不是在末尾)

  • 即使如此,sqlalchemy也不喜欢它们都被命名为
    NewTable
    。声明性ORM评估您的类定义,因此在设置
    \uuuu name\uuuu
    之前,它会查看
    NewTable
    。解决方案是不使用声明性系统(请参阅文档中的“经典映射”)

  • 但另一种方法是扩展声明性元类以处理名称更改。
    declarative_base
    函数接受一个显式的
    元类
    参数,因此这似乎在框架的规范范围内。要使用下面的方法,可以在
    NewTable
    定义中设置
    \uu name=“vector\u ORM{}”.format(name)
    。如果你想变得干净,也要更新
    \uuuuuuqalname\uuuuu
    ,尽管sqlalchemy在任何地方都不使用它

来自sqlalchemy.ext.declarative导入declarative_base,DeclarativeMeta
类NamingDeclarativeMeta(DeclarativeMeta):
定义初始化(cls、类名、基、dict):
如果cls中的“\uuuuu name\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
cls.\uuuuuu name\uuuuuuuu=classname=cls.\uuuuuu dict\uuuuuuuuu[''uuuuuuuu name\uuuuuuuu']
DeclarativeMeta.\uuuuu init\uuuuuu(cls、类名、基、dict)
Base=declarative_Base(元类=NamingDeclarativeMeta)

如果发布创建表代码,则更容易了解具体问题所在。