我在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并查看它是否有效更可靠。在此期间,我们非常感谢任何帮助。
答案 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指出我正确的方向!