【发布时间】:2013-05-09 13:06:46
【问题描述】:
早在 2010 年 10 月,我在 Sqlalchemy 用户列表中发布了 this question。
当时,我只是使用了消息中提到的clear_mappers 解决方法,并没有尝试找出问题所在。这对我来说很淘气。今天我再次遇到了这个错误,并决定构建一个最小的示例,如下所示。早在 2006 年,Michael 还谈到了 probably the same issue。我决定在这里跟进,让 Michael 从我的愚蠢问题中解脱出来。
因此,结果似乎是对于给定的类定义,您不能定义多个映射器。在我的情况下,我在模块范围内声明了 Pheno 类(我假设这里是顶级范围)并且每次 make_tables 运行时,它都会尝试定义另一个映射器。
Mike 写道:“根据上述问题的描述,您需要确保您的 Python 类与映射器在同一范围内声明。您收到的错误消息表明 'Pheno' 是在模块级别声明的。”这会解决问题,但我如何在不改变当前结构的情况下管理它?如果有的话,我还有什么其他选择?显然映射器没有像“如果映射器已经定义,则退出而不做任何事情”这样的选项,这会很好地处理它。我想我可以定义一个包装函数,但这会很丑。
from sqlalchemy import *
from sqlalchemy.orm import *
def make_pheno_table(meta, schema, name='pheno'):
pheno_table = Table(
name, meta,
Column('patientid', String(60), primary_key=True),
schema=schema,
)
return pheno_table
class Pheno(object):
def __init__(self, patientid):
self.patientid = patientid
def make_tables(schema):
from sqlalchemy import MetaData
meta = MetaData()
pheno_table = make_pheno_table(meta, schema)
mapper(Pheno, pheno_table)
table_dict = {'metadata': meta, 'pheno_table':pheno_table}
return table_dict
table_dict = make_tables('foo')
table_dict = make_tables('bar')
错误信息如下。在 Debian 挤压上使用 SQLAlchemy 0.6.3-3 进行测试。
$ python test.py
Traceback (most recent call last):
File "test.py", line 25, in <module>
table_dict = make_tables('bar')
File "test.py", line 20, in make_tables
mapper(Pheno, pheno_table)
File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/__init__.py", line 818, in mapper
return Mapper(class_, local_table, *args, **params)
File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/mapper.py", line 209, in __init__
self._configure_class_instrumentation()
File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/mapper.py", line 381, in _configure_class_instrumentation
self.class_)
sqlalchemy.exc.ArgumentError: Class '<class '__main__.Pheno'>' already has a primary mapper defined. Use non_primary=True to create a non primary Mapper. clear_mappers() will remove *all* current mappers from all classes.
编辑:根据SQLAlchemy: The mapper() API 中的文档,我可以将上面的mapper(Pheno, pheno_table) 替换为
from sqlalchemy.orm.exc import UnmappedClassError
try:
class_mapper(Pheno)
except UnmappedClassError:
mapper(Pheno, pheno_table)
如果没有为 Pheno 定义映射器,它会抛出 UnmappedClassError。这至少不会在我的测试脚本中返回错误,但我还没有检查它是否真的有效。评论?
EDIT2:根据丹尼斯的建议,以下工作:
class Tables(object):
def make_tables(self, schema):
class Pheno(object):
def __init__(self, patientid):
self.patientid = patientid
from sqlalchemy import MetaData
from sqlalchemy.orm.exc import UnmappedClassError
meta = MetaData()
pheno_table = make_pheno_table(meta, schema)
mapper(Pheno, pheno_table)
table_dict = {'metadata': meta, 'pheno_table':pheno_table, 'Pheno':Pheno}
return table_dict
table_dict = Tables().make_tables('foo')
table_dict = Tables().make_tables('bar')
然而,表面上相似
# does not work
class Tables(object):
class Pheno(object):
def __init__(self, patientid):
self.patientid = patientid
def make_tables(self, schema):
from sqlalchemy import MetaData
from sqlalchemy.orm.exc import UnmappedClassError
meta = MetaData()
pheno_table = make_pheno_table(meta, schema)
mapper(self.Pheno, pheno_table)
table_dict = {'metadata': meta, 'pheno_table':pheno_table, 'Pheno':self.Pheno}
return table_dict
table_dict = Tables().make_tables('foo')
table_dict = Tables().make_tables('bar')
没有。我收到与以前相同的错误消息。
我不太了解范围界定问题,无法说出原因。
在这两种情况下,Pheno 类不是在某种本地范围内吗?
【问题讨论】:
标签: sqlalchemy