2014-02-20 52 views
0

我試着打造「包裝」,它通過SQLAlchemy的ORM與DB工作,但返回結果的問題:得到錯誤「遞延實例沒有屬性‘__的GetItem __’」Deferreds並返回結果

如何我可以修復這個?

源代碼: 一個)db_decorators.py

from twisted.internet import threads 
from sqlalchemy import create_engine, pool 
from sqlalchemy.orm import sessionmaker 


def toThread(func): 
    def wrapper(*args, **kwargs): 
     return threads.deferToThread(func, *args, **kwargs) 
    return wrapper 

class DBDefer(object): 
    def __init__(self, dsn, poolclass=pool.SingletonThreadPool): 
     self.engine = create_engine(dsn, poolclass=poolclass) 

    def __call__(self, func): 
     @toThread 
     def wrapper(*args, **kwargs): 
      session = sessionmaker(bind=self.engine)() 
      try: 
       return func(session=session, *args, **kwargs) 
      except: 
       session.rollback() 
       raise 
      finally: 
       session.close() 
     return wrapper  

b)中connector.py

import sqlalchemy 
from twisted.internet.defer import Deferred 
from db_decorators import DBDefer 
from tables import Users 

dbdefer = DBDefer('postgresql://test:[email protected]/testdb') 

@dbdefer 
def find_user_by_login(user_login, session=None): 
    return session.execute(sqlalchemy.select([Users]).where(Users.name == user_login)).fetchone() 


class DB_API(object): 

    def find_user_by_login(self, user_login): 
     d = Deferred() 
     def _gotResult(user): 
      if user is None: 
       d.errback('No such user') 
      else: 
       d.callback(dict(user)) 
      return user 
     find_user_by_login(user_login).addCallbacks(_gotResult, d.errback) 
     return d 

c)中某處server.py(上扭曲服務器)

def authorization(self, data): 
    """ 
     Checking user with DB 
    """ 
    log.msg("[AUTH] User=%s trying to auth..." % data['user']) 
    #session = self.Session() 
    #result = session.execute(sqlalchemy.select([Users]).where(Users.name == data['user'])) 
    #result = result.fetchone() 
    #session.close() 

    result = self.db_api.find_user_by_login(data['user']) 
    data, result_msg = commands.AUTH(result, data) 
    log.msg(result_msg) 
    return data 

回溯:

Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/dist-packages/twisted/python/log.py", line 88, in callWithLogger 
    return callWithContext({"system": lp}, func, *args, **kw) 
    File "/usr/local/lib/python2.7/dist-packages/twisted/python/log.py", line 73, in callWithContext 
    return context.call({ILogContext: newCtx}, func, *args, **kw) 
    File "/usr/local/lib/python2.7/dist-packages/twisted/python/context.py", line 118, in callWithContext 
    return self.currentContext().callWithContext(ctx, func, *args, **kw) 
    File "/usr/local/lib/python2.7/dist-packages/twisted/python/context.py", line 81, in callWithContext 
    return func(*args,**kw) 
--- <exception caught here> --- 
    File "/usr/local/lib/python2.7/dist-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite 
    why = selectable.doRead() 
    File "/usr/local/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 215, in doRead 
    return self._dataReceived(data) 
    File "/usr/local/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 221, in _dataReceived 
    rval = self.protocol.dataReceived(data) 
    File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/tls.py", line 419, in dataReceived 
    self._flushReceiveBIO() 
    File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/tls.py", line 389, in _flushReceiveBIO 
    ProtocolWrapper.dataReceived(self, bytes) 
    File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/policies.py", line 120, in dataReceived 
    self.wrappedProtocol.dataReceived(data) 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/twisted/websocket.py", line 78, in dataReceived 
    self._dataReceived(data) 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1270, in _dataReceived 
    self.consumeData() 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1286, in consumeData 
    while self.processData() and self.state != WebSocketProtocol.STATE_CLOSED: 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1445, in processData 
    return self.processDataHybi() 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1758, in processDataHybi 
    fr = self.onFrameEnd() 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1887, in onFrameEnd 
    self._onMessageEnd() 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/twisted/websocket.py", line 107, in _onMessageEnd 
    self.onMessageEnd() 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 734, in onMessageEnd 
    self._onMessage(payload, self.message_is_binary) 
    File "/usr/local/lib/python2.7/dist-packages/autobahn/twisted/websocket.py", line 110, in _onMessage 
    self.onMessage(payload, isBinary) 
    File "server.py", line 80, in onMessage 
    json_data = self.commands_handlers['AUTH'](json_data) 
    File "server.py", line 64, in authorization 
    data, result_msg = commands.AUTH(result, data) 
    File "/home/relrin/code/Helenae/helenae/commands.py", line 68, in AUTH 
    if result['name'] == data['user']: 
exceptions.AttributeError: Deferred instance has no attribute '__getitem__' 
+0

請包括* full *回溯,以便我們可以看到您發生此錯誤的位置。如果沒有這樣的話,我只能猜測錯誤是在'authorization'的某個地方,在那裏你做了一個'authorization(something())'而不是'something()。addCallback(authorization)'。 – SingleNegationElimination

回答

3

self.db_api.find_user_by_login(data['user'])返回Deferred

使用它的代碼 - data, result_msg = commands.AUTH(result, data) - 忽視了這個事實,並將其當作結果對待。

問題中的一半代碼正確使用Deferred。例如,這是正確的:

find_user_by_login(user_login).addCallbacks(_gotResult, d.errback) 

但是,發生錯誤的代碼不會嘗試定義或設置任何回調。它試圖使用Deferred就好像它是一個結果 - 事實並非如此。

您需要使用addCallback等等。

如果你想使用SQLAlchemy和Twisted在一起,還可以考慮看看alchimia