将类分隔为单独的文件时,元类冲突

时间:2014-04-09 21:04:32

标签: python sqlalchemy

修改

问题在于导入。我应该做的是写:from SomeInterface import SomeInterface。我真的应该根据Python styleguide (PEP 8)以小写someinterface.py编写模块名称。


我有一个文件model.py,它定义了与我的数据库相关的所有类,并实例化了我的Base。

# model.py
metadata = MetaData()
DeclarativeBase = declarative_base()
metadata = DeclarativeBase.metadata

class Bar(DeclarativeBase):
    __tablename__ = 'Bar'
    __table_args__ = {}
    # column and relation definitions

文件model.py是自动生成的,所以我无法触及它。我所做的是创建一个名为modelaugmented.py的文件,我通过继承为一些模型类添加额外的功能。

# modelaugmented.py
from model import *
import SomeInterface

class BarAugmented(Bar, SomeInterface):
    pass

# SomeInterface.py
class SomeInterface(object):
    some_method(): pass

我遇到的问题是,对于像BarAugmented这样的课程,我收到以下错误:

 TypeError: Error when calling the metaclass bases
 metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

SomeInterface位于单独的文件中而不是位于modelaugmented.py内时,我才会收到此错误。

我了解SomeInterfaceBar的元类不同。问题是我无法弄清楚如何解决这个问题。我尝试了Triple inheritance causes metaclass conflict... Sometimes中建议的解决方案,该解决方案适用于给出的示例,但不是我的情况。不确定SqlAlchmey是否与它有任何关系。

class MetaAB(type(DeclarativeBase), type(SomeInterface)):
    pass

class BarAugmented(Bar, SomeInterface):
    __metaclass__ = MetaAB

但后来我收到了错误:

TypeError: Error when calling the metaclass 
bases multiple bases have instance lay-out conflict

使用SQLAlchemy 0.8和Python 2.7。

1 个答案:

答案 0 :(得分:1)

好的,一定有一些我不知道的东西,因为我为你创建了一个类似的文件布局(我认为),它可以在我的机器上运行。我很感激你让你的问题简短而简单,但也许缺少一些改变......的东西? Dunno ......(也许SomeInterface有一个abc.abstract元类?)如果您更新了问题,请通过对此答案的评论告诉我,我会尝试更新我的答案。

这就是:

档案stack29A.py (相当于您的model.py):

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session

DSN = "mysql://root:foobar@localhost/so_tests?charset=utf8"
engine = create_engine(DSN)
Session = scoped_session(sessionmaker(bind=engine))
session = Session()

DeclarativeBase = declarative_base()

class Bar(DeclarativeBase):
    __tablename__ = 'Bar'
    _id = Column('_id', Integer, primary_key=True)
    email = Column('email', String(50)) 

档案stack29B.py (相当于您的someinterface.py):

class SomeInterface(object):
    def some_method(self):
        print "hellou"   

档案stack29C.py (相当于您的modelaugmented.py):

from stack29A import Bar
from stack29B import SomeInterface

class BarAugmented(Bar, SomeInterface):
    pass

文件stack29D.py (就像一种main.py:表创建者和示例):

from stack29C import BarAugmented
from stack29A import session, engine, DeclarativeBase

if __name__ == "__main__":
    DeclarativeBase.metadata.create_all(engine)
    b1 = BarAugmented()
    b1.email = "foo@bar.baz"
    b2 = BarAugmented()
    b2.email = "baz@bar.foo"
    session.add_all([b1, b2])
    session.commit()
    b3 = session.query(BarAugmented)\
                    .filter(BarAugmented.email == "foo@bar.baz")\
                    .first()
    print "b3.email: %s" % b3.email                    
    b3.some_method()

如果我运行" main"文件(stack29D.py)一切都按预期工作:

(venv_SO)borrajax@borrajax:~/Documents/Tests$ python ./stack29D.py
b3.email: foo@bar.baz
hellou