3

我试图理解为什么当我尝试评估单元格的内容时会出现以下错误,某些函数要么没有返回,要么我不明白这些东西是如何工作的。

 2012-11-08 04:30:45-0800 [HTTPPageGetter,client] handling data: None
 2012-11-08 04:30:45-0800 [HTTPPageGetter,client] Unhandled Error
 Traceback (most recent call last):
 File "path/to/python/lib/python2.7/site-packages/twisted/internet/defer.py", line 1101, in gotResult
 _inlineCallbacks(r, g, deferred)
 File "path/to/python/lib/python2.7/site-packages/twisted/internet/defer.py", line 1048, in _inlineCallbacks
 deferred.callback(None)
 File "path/ib/python2.7/site-packages/twisted/internet/defer.py", line 368, in callback
 self._startRunCallbacks(result)
 File "path/lib/python2.7/site-packages/twisted/internet/defer.py", line 464, in _startRunCallbacks
 self._runCallbacks()
 --- <exception caught here> ---
 File "path/lib/python2.7/site-packages/twisted/internet/defer.py", line 551, in _runCallbacks
 current.result = callback(current.result, *args, **kw)
 File "/path/to/lib/python2.7/site-packages/codenode/frontend/async/backend.py", line 223, in _success
 if 'cellstyle' in data and data['cellstyle'] == 'outputimage':
 exceptions.TypeError: argument of type 'NoneType' is not iterable

 2012-11-08 04:30:45-0800 [HTTPPageGetter,client] Stopping factory

这是代码的相关部分(我认为): addcallback 中有一个可疑部分(三个参数都不是数据)但在 _success 中(三个除了 self 一个是数据),如果这是问题何时我传递数据?

def render(self, request):
    """
    This is where we un-serialize the content sent between the frontend
    and backend engine bus.
    """
    content = request.content.read()
    if content:
        msg = json.loads(content)
        log.msg('Engine message deserialized %s' % str(msg))
    else:
        return
    cellid = msg.get('cellid', '')
    d = self.engine_bus.handleRequest(self.notebook_id, msg)
    d.addCallback(self._success, request, cellid)
    d.addErrback(self._fail, request)
    return server.NOT_DONE_YET

def _success(self, data, request, cellid):
    """
    horrible. not always eval...
    """
    log.msg('handling data: %s' % str(data))
    if 'cellstyle' in data and data['cellstyle'] == 'outputimage':
        image_data = pickle.loads(data['out']).getvalue()
        image_file_name = write_image(image_data)
        data['out'] = image_file_name

    data['cellid'] = cellid
    jsobj = json.dumps(data)
    request.write(jsobj)
    request.finish()

诚然,这不是自己的作品,我对它知之甚少,而且它已经过时了。这是更多代码: github python文件

[编辑] 这里还有一点:初始化:

class EngineSessionAdapter(resource.Resource):
    """
    There should be a better way to do this, have to figure that out.
    """

    isLeaf = True

    def __init__(self, engine_bus, notebook_id):
        resource.Resource.__init__(self)
        self.engine_bus = engine_bus
        self.notebook_id = notebook_id
        self.putChild("", self)

这是引擎对象:

class EngineBusAdapter(resource.Resource):

    def __init__(self, engine_bus):
        resource.Resource.__init__(self)
        self.engine_bus = engine_bus
        self.putChild("", self)

    def getChild(self, path, request):
        """XXX Can this refer back to itself?
        """
        return EngineSessionAdapter(self.engine_bus, path)

[第 2 次编辑] 这是 Enginebus 定义:

class EngineBus(object):
"""
Common entry point for all engine requests. 
Look up engine client by access_id.

This is responsible for routing the engine message
from the browser/frontend to the engine by access_id.
This does not need to process the message (un-serialize, inspect, 
or otherwise).
"""

def __init__(self, backend):
    self.backend = backend

@defer.inlineCallbacks
def handleRequest(self, access_id, msg):
    """
    msg comes in as dictionary
    """
    log.msg('handling engine request for %s' % access_id)
    try:
        engine_client = yield self.backend.getEngine(access_id)
        log.msg('got engine Client %s' % str(engine_client))
    except InvalidAccessId:
        err = {'status':'ERR', 'response':'InvalidAccessId'}
        log.err('InvalidAccessId %s' % access_id)
        defer.returnValue(err)

    result = yield engine_client.send(msg)
    sucs = {'status':'OK', 'response':result}
    defer.returnValue(sucs)

编辑:终于解决了:这里是差异:

-        result = yield meth(engine_arg, cellid)
+        result = yield defer.maybeDeferred(meth,engine_arg, cellid)
         defer.returnValue(result)

-    @defer.inlineCallbacks
     def engine_start(self, args, arg):
         """dummy
         """
-        defer.returnValue({'result':'started'})
+        return {'result':'started'}

这里是上下文:github上后端/engine.py的提交差异

4

2 回答 2

4

鉴于此源代码行:

if 'cellstyle' in data and data['cellstyle'] == 'outputimage':

你得到的例外:

exceptions.TypeError: argument of type 'NoneType' is not iterable

几乎可以肯定的意思dataNone。由于data是你附加到 a 的回调的结果参数(即第一个参数)Deferred,这意味着DeferredNone的结果是 。

由于Deferred这个回调附加到是这样创建的:

d = self.engine_bus.handleRequest(self.notebook_id, msg)

似乎这engine_bus.handleRequest给了你一个DeferredNone. 也许这是engine_bus对象中的一个错误,或者您滥用了该 API?我不确定是什么engine_bus,所以我无法进一步挖掘。

于 2012-11-08T14:19:46.233 回答
3
if 'cellstyle' in data and data['cellstyle'] == 'outputimage':
exceptions.TypeError: argument of type 'NoneType' is not iterable

'cellstyle' in data需要data是可迭代的 - 它不是可迭代的,但是None

于 2012-11-08T14:18:03.123 回答