Python 使用动态表格生成完全刷新SQLAlchemy
我需要在for循环中的不同位置创建许多类似的数据库。在循环的开始,我在磁盘上创建了一个新的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()
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也不喜欢它们都被命名为
。声明性ORM评估您的类定义,因此在设置NewTable
之前,它会查看\uuuu name\uuuu
。解决方案是不使用声明性系统(请参阅文档中的“经典映射”)NewTable
- 但另一种方法是扩展声明性元类以处理名称更改。
函数接受一个显式的declarative_base
参数,因此这似乎在框架的规范范围内。要使用下面的方法,可以在元类
定义中设置NewTable
。如果你想变得干净,也要更新\uu name=“vector\u ORM{}”.format(name)
,尽管sqlalchemy在任何地方都不使用它\uuuuuuqalname\uuuuu
来自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)
如果发布创建表代码,则更容易了解具体问题所在。