2014-07-05 94 views
0

我已經使用Flask和flask-restful在Google App Engine上編寫了一個非常簡單的REST API。API旨在用於表示關於慈善機構的數據。籌款活動在這種情況下的自行車騎間歇燒瓶/燒瓶,GAE'對象'不可調用類型錯誤

一切似乎只是我間歇獲得從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網址的時間。另外50%的時間工作正常。我使用App Engine SDk獲得了與本地盒子相同的失敗率,並部署到App Engine。但是,當我連接調試器時,我沒有得到它給出的錯誤。通過添加調試打印調用,我已經確定,當它失敗時,它會在for循環的第一次迭代中失敗,並且d確實是一個帶有我試圖訪問的鍵和值的字典。

我對Python,Flask和App Engine很新,所以我肯定會在這裏丟失一些東西,但是我已經閱讀了我找到的所有「對象不可調用」的帖子,而且我還沒有發現任何似乎適用的東西即我不缺少構造函數的一部分,我沒有將對象重新分配給另一個類型,並且我沒有重寫基類型(我已經能夠找到)。

我不知道這是FLASK問題,Python問題,燒瓶問題,App Engine問題還是我的問題,所以我的下一步是僅使用Flask重做API並查看它是否是它工作更可靠。在此期間,任何幫助非常感謝。

+1

這聽起來好像您已將實例分配給'Models.RiderStatus';例如*代碼中的其他地方*最終直接或間接地執行'Models.RiderStatus = Models.RiderStatus()'。從那裏開始*那個進程*被破壞並將繼續拋出該異常。 –

+0

這可能是問題嗎?這與最經常失敗的URL在同一個類中定義: 'def get(self,rider_id): statuses = Models.RiderStatus.last_status(rider_id).fetch() return jsonify({'statuses':[ Models.RiderStatus.to_dict()Models.RiderStatus in status]})' 我將最後一行改爲: 'return jsonify({'statuses':[s.to_dict()for s in status)})' – mabeeenigma

+0

是的,在Python 2中肯定可以做到這一點。 「Model.RiderStatus」這個名稱對於列表理解來說不是本地的。 –

回答

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指引我走向正確的方向!