延期和退货结果

时间:2014-02-20 18:53:55

标签: python python-2.7 asynchronous twisted

我试图创建“包装器”,它通过SQLAlchemy ORM与DB一起工作,但返回结果的问题:获取错误“延迟实例没有属性'__ getitem __'”

我如何解决这个问题?

源代码: a)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:test@localhost/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中的某个地方(Twisted上的服务器)

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__'

1 个答案:

答案 0 :(得分: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