间歇烧瓶/烧瓶,GAE'对象"不可调用类型错误

时间:2014-07-05 03:27:18

标签: google-app-engine python-2.7 flask flask-restful

我在Google App Engine上使用Flask和flask-restful编写了一个非常简单的REST API。该API旨在用于表示有关慈善筹款活动的数据。在这种情况下骑自行车。

除了我间歇性地从App Engine的日志中获取以下堆栈跟踪中显示的类型错误之外,一切似乎都在起作用:

Internal Error
Traceback (most recent call last):
  File "/base/data/home/apps/s~agonytrackertest/1.376935219653445037/lib/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/base/data/home/apps/s~agonytrackertest/1.376935219653445037/lib/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/base/data/home/apps/s~agonytrackertest/1.376935219653445037/lib/flask_restful/__init__.py", line 397, in wrapper
    resp = resource(*args, **kwargs)
  File "/base/data/home/apps/s~agonytrackertest/1.376935219653445037/lib/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/base/data/home/apps/s~agonytrackertest/1.376935219653445037/lib/flask_restful/__init__.py", line 487, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/base/data/home/apps/s~agonytrackertest/1.376935219653445037/main.py", line 268, in post
    supersedes=d['Supersedes'])
TypeError: 'RiderStatus' object is not callable

RiderStatus对象的定义如下:

class RiderStatus(ndb.Model):
    """ Models a status for a Rider with rider_id, location, action, time_stamp
        status_id
    """

    rider_number = ndb.IntegerProperty(indexed=True, required=True)
    location = ndb.StringProperty(indexed=False, required=True)
    state = ndb.StringProperty(indexed=False, required=True)
    time_recorded = ndb.DateTimeProperty(auto_now_add=True)
    time_occurred = ndb.IntegerProperty(indexed=False, required=True)
    status_id = ndb.StringProperty(indexed=True, required=True)
    status_origin = ndb.StringProperty(indexed=True, required=True)
    supersedes = ndb.StringProperty(indexed=False, required=True)

日志中调出的代码部分是创建一个新的RiderStatus对象,如下所示:

for d in statuses:
            created_count += 1
            status = Models.RiderStatus(rider_number=d['RiderNumber'],
                                        location=d['Location'], state=d['State'], time_occurred=d['TimeStamp'],
                                        status_id=d['StatusId'], status_origin=d['StatusOrigin'],
                                        supersedes=d['Supersedes'])
            status.put()
return {"created":str(created_count)}, 201

我认为可能是我初始化对象的方式,虽然我理解前面的内容常用于Python,所以我为类和初始化方法创建了一个显式构造函数。然后班级看起来像这样:

class RiderStatus(ndb.Model):
    """ Models a status for a Rider with rider_id, location, action, time_stamp
        status_id
    """
    def __init__(self, rider_number=0, location='', state='', time_occurred=0, status_id='', status_origin='',
                 supersedes=''):
        super(RiderStatus, self).__init__()
        self.rider_number = rider_number
        self.location = location
        self.state = state
        self.time_occurred = time_occurred
        self.status_id = status_id
        self.status_origin = status_origin
        self.supersedes = supersedes

    rider_number = ndb.IntegerProperty(indexed=True, required=True)
    location = ndb.StringProperty(indexed=False, required=True)
    state = ndb.StringProperty(indexed=False, required=True)
    time_recorded = ndb.DateTimeProperty(auto_now_add=True)
    time_occurred = ndb.IntegerProperty(indexed=False, required=True)
    status_id = ndb.StringProperty(indexed=True, required=True)
    status_origin = ndb.StringProperty(indexed=True, required=True)
    supersedes = ndb.StringProperty(indexed=False, required=True)

    def make_rider_status(self, in_dict):
        self.rider_number = in_dict['RiderNumber']
        self.location = in_dict['Location']
        self.state = in_dict['State']
        self.time_occurred = in_dict['TimeStamp']
        self.status_id = in_dict['StatusId']
        self.status_origin = in_dict['StatusOrigin']
        self.supersedes = in_dict['Supersedes'] 

创作看起来像这样:

for d in statuses:
            created_count += 1
            status = Models.RiderStatus()
            status.make_rider_status(d)
            status.put()
return {"created":str(created_count)}, 201

我得到了类似的错误:

Internal Error
Traceback (most recent call last):
  File "/base/data/home/apps/s~agonytrackermain/1.377017814438367636/lib/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/base/data/home/apps/s~agonytrackermain/1.377017814438367636/lib/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/base/data/home/apps/s~agonytrackermain/1.377017814438367636/lib/flask_restful/__init__.py", line 397, in wrapper
    resp = resource(*args, **kwargs)
  File "/base/data/home/apps/s~agonytrackermain/1.377017814438367636/lib/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/base/data/home/apps/s~agonytrackermain/1.377017814438367636/lib/flask_restful/__init__.py", line 487, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/base/data/home/apps/s~agonytrackermain/1.377017814438367636/main.py", line 283, in post
    status = Models.RiderStatus()
TypeError: 'RiderStatus' object is not callable

我收到此错误可能大约有50%的时间我发布到该API URL。其他50%的时间它工作正常。我得到了与App Engine SDk在本地盒子上运行的相同故障率并部署到App Engine。但是,当我连接调试器时,我还没有得到错误。通过添加调试打印调用,我已经确定当它失败时,它会在第一次迭代中通过for循环失败,而d确实是一个带有我想要访问的键和值的字典。

我是Python,Flask和App Engine的新手,所以我肯定会在这里遗漏一些东西,但我已经阅读了所有"对象无法调用"我发现的帖子,我没有找到任何似乎适用的东西,即我没有错过构造函数的一部分,我没有将对象重新分配给另一种类型,并且我没有覆盖基类型(我已经能够找到)无论如何)。

我不知道这是一个FLASK问题,一个Python问题,一个烧瓶问题,一个App Engine问题,还是我的问题所以我的下一步是仅使用Flask重做API并查看它是否有效更可靠。在此期间,我们非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

如上述评论中所述,我在进一步考虑Martijn Pieters所建议的内容后找到了答案。答案是在对问题的评论中,但我认为我会更加明显,希望它对其他人有用。

我使用代码创建了列表解析:

def get(self, rider_id):          
    statuses = Models.RiderStatus.last_status(rider_id).fetch()
    return jsonify({'statuses': [Models.RiderStatus.to_dict() for Models.RiderStatus in
    statuses]})

我理解导致问题的原因如下:此模式导致将 Models.RiderStatus的实例分配给名为Models.RiderStatus的对象。然后对Models.RiderStatus的后续调用尝试访问该实例,就好像它是导致类型错误的类一样。上面的最后一行实际上应该是:

return jsonify({'statuses': [s.to_dict() for s in statuses]})

Martijn的评论暗示第一个模式在Python 3中可能没问题,但在Python 2中是错误的。我理解在Python 3中如何处理类对象有很多变化,但我不知道如何验证或扩展评论。

问题的间歇性与访问URI的顺序有关。使用“正确”顺序,问题变得更加明显。

再次感谢Martijn指出我正确的方向!