【问题标题】:Inheritance Issue: AttributeError: 'str' object has no attribute '_sa_instance_state'继承问题:AttributeError:“str”对象没有属性“_sa_instance_state”
【发布时间】:2015-10-13 21:19:02
【问题描述】:

问题:继承类没有检查字符串,因为它是作为None 传递的。

retrieve 方法的父类 (object.py) 旨在从数据库中检索对象(例如 id 或用户/评估组合)。子类 (convenience.py) 旨在接受这些对象的 strs。

object.py

def retrieve_assessment_result(self, *args):
    id, owner, assessment = None, None, None
    if len(args) == 1:
        id, = args # or id = args[0]
    elif len(args) == 2:
        owner, assessment = args
        print 'testa', owner, assessment, id
    else:
        raise ValueError('Value being passed is an object')
    if id is not None:
        print 'testi', id
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.id == id).one()
    elif owner is not None:
        print 'testo', owner
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.owner == owner).one()
    elif assessment is not None:
        print 'testa', assessment
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.assessment == assessment).one()

convenience.py

def retrieve_assessment_result(self, *args):
    id, owner, assessment = None, None, None
    if len(args) == 1:
        id, = args # or id = args[0]
        print " args = ", args
    elif len(args) == 2:
        username, name = args
        print "api args = ", args
        print 'type args', type(args)
        print 'owner: ', owner
        print 'assessment: ', assessment
    if owner is not None:
        owner = self.retrieve_user(username)
    if assessment is not None:
        assessment = self.retrieve_assessment(name)
    return super(ConvenienceAPI, self).retrieve_assessment_result(*args)

test.py

api.retrieve_assessment_result('baseball', 'Becoming a Leader')

回溯错误:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/ack/code/venv/NotssDB/notssdb/test/test.py", line 133, in test1
    api.retrieve_assessment_result('baseball', 'Becoming a Leader')
  File "/Users/ack/code/venv/NotssDB/notssdb/api/convenience.py", line 42, in retrieve_assessment_result
    return super(ConvenienceAPI, self).retrieve_assessment_result(*args)
  File "/Users/ack/code/venv/NotssDB/notssdb/api/object.py", line 327, in retrieve_assessment_result
    filter(Assessment_Result.owner == owner).one()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/operators.py", line 301, in __eq__
    return self.operate(eq, other)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 175, in operate
    return op(self.comparator, *other, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1011, in __eq__
    other, adapt_source=self.adapter))
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1338, in _optimized_compare
    state = attributes.instance_state(state)
AttributeError: 'str' object has no attribute '_sa_instance_state'
------output--------
<Assessment_Result(owner='<User(username ='bambam', firstname ='Sean', lastname ='Cargo', email='car@gmail.com')>', assessment='<Assessment(name='Foo', text='this is foo')>')>
api args =  ('baseball', 'Becoming a Leader')
type args <type 'tuple'>
owner:  None
assessment:  None
testa baseball Becoming a Leader None
testo baseball

-----评论/建议后更新:
object.py 更新:

def retrieve_assessment_result(self, id=None, owner=None, assessment=None):
    print 'test_all_objects', owner, assessment, id
    if id is not None:
        print 'test_id_object', id
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.id == id).one()
    elif owner is not None:
        print 'test_owner_object', owner
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.owner.has(User.username == username)).one()
    elif assessment is not None:
        print 'test_assessment_object', assessment
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.assessment.has(Assessment.name == name)).one()

Convenience.py(继承自object.py)更改:

def retrieve_assessment_result(self, id=None, owner=username, assessment=name):
    if owner is not None:
        owner = self.retrieve_user(username)
    if assessment is not None:
        assessment = self.retrieve_assessment(name)
    return super(ConvenienceAPI, self).retrieve_assessment_result(id=None, owner=owner, assessment=assessment)

追溯:

  File ".../api/convenience.py", line 6, in <module>
    class ConvenienceAPI(BaseAPI):
  File "../api/convenience.py", line 37, in ConvenienceAPI
    def retrieve_assessment_result(self, id=None, owner=username, assessment=name):
NameError: name 'username' is not defined

【问题讨论】:

  • 不应该是返回 super(ConvenienceAPI, self).retrieve_assessment_result(id=None, owner=owner,assessment=name)?
  • @pi。仍然有这个问题。最初的设计有问题(正如你所建议的那样)。

标签: python attributes sqlalchemy traceback


【解决方案1】:

根据我的经验,错误 '???' object has no attribute '_sa_instance_state 几乎总是表明您将不是 SQLAlchemy 对象的东西(即一些基本类型,如 int、str 等)分配给 @987654323 @ 或dynamic_loader

relationship例子

>>> result = db.query(Assessment_Result).first()
>>> # owner only accepts Owner objects
>>> result.owner = "Mr. Harvey Example"
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute '_sa_instance_state'

此外,在relationship 上使用其他类型进行过滤也会导致此错误:

过滤示例

>>> Assessment_Result.owner == "baseball"
Traceback (most recent call last):
...
AttributeError: 'str' object has no attribute '_sa_instance_state'

在您的情况下,错误是由于将字符串 "baseball" 作为您传递给 Object.retrieve_assessment_result 的 2 元组 args 中的第一个条目,然后将其放入变量 owner在第二个 if 块中。

>>>         owner, assessment = args

由于owner 现在包含str,当您使用它进行过滤时,这将失败。

我想借此机会指出,这段代码的可读性不是很好,可以通过使用 keyword arguments 来改进,并且通常会使其更简洁。

【讨论】:

  • 是的,这就是我在上面指出并在打印输出中显示的内容。 Convenience.py 应该允许字符串,但是如果您查看回溯打印输出,Owner 正在打印None ...我认为它来自convenience.py ...由于某种原因继承不起作用并导致此问题。
  • 你建议我使用类似的东西:retrieve_assessment_result(id=none, owner=none, assessment=none) ...但这不会导致同样的问题吗?另外,你的回答非常有说服力。
  • 仅当您将字符串传递给owner 时,此错误会更加明显,因为没有元组解包代码会掩盖问题。此外,为了更明显,您可以直接在方法的开头添加 assert 语句,检查正确的类型。
  • 知道了,我可以进行这些更改...convenience.py 的重点是传递字符串,因为检索方法将int 用于idstr 用于owner 或@ 987654345@。便利性.py的设计很差吗?
  • 尽量使用尽可能少的代码。更少的代码意味着更少的可能出错的东西。与separation of concerns 结合使用,可以大大改进代码。只要尝试改进它,最终一切都会好起来的。 :)
猜你喜欢
  • 1970-01-01
  • 2016-01-10
  • 2021-12-27
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 2023-03-17
相关资源
最近更新 更多