我在使用Twisted时只是跟踪了一个随机错误:
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/twisted/spread/pb.py", line 826, in proto_message
self._recvMessage(self.localObjectForID, requestID, objectID, message, answerRequired, netArgs, netKw)
File "/usr/lib/python2.7/dist-packages/twisted/spread/pb.py", line 840, in _recvMessage
netResult = object.remoteMessageReceived(self, message, netArgs, netKw)
File "/usr/lib/python2.7/dist-packages/twisted/spread/flavors.py", line 114, in remoteMessageReceived
state = method(*args, **kw)
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1141, in unwindGenerator
return _inlineCallbacks(None, f(*args, **kwargs), Deferred())
--- <exception caught here> ---
File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1020, in _inlineCallbacks
result = g.send(result)
exceptions.AttributeError: 'NoneType' object has no attribute 'send'
这是由以下原因引起的:
@defer.inlineCallbacks
def myfunc():
# Function implementation with no yield statement.
当myfunc
被调用时,我会打印出之前的回溯,但函数内的所有内容都能正常工作。这是因为它在调用时返回None
而不是生成器,defer.inlineCallbacks
期望返回它。有没有办法将函数声明为生成器而不在函数体中放置yield语句?比如发电机装饰器?
答案 0 :(得分:6)
正如其他人所说,这可能毫无意义。但为了完整性并回答这个问题:
否,您必须使用yield
使其成为生成器,当然,如果您创建一个生成器的装饰器(通过包含yield
关键字)本身,但实际上并没有产生任何东西,只是调用装饰函数。这样的yield
可以无法访问且毫无意义(if False: yield
),但它必须存在。由于这不是常见的需求,因此没有像预先构建的那样,至少我没有意识到。最简单的方法是将它添加到你的函数中,编写你自己的装饰器在一些情况下是不值得的,如果你经常需要它,没有你的设计可能有问题,你应该修改它。
答案 1 :(得分:1)
如果你真的需要它,那就做一个。
#like this
def generator(callable):
def asgenerator(*args, **kwargs):
while True:
yield callable(*args, **kwargs)
return asgenerator
虽然如其他人所说,这可能隐藏了一个设计问题。
答案 2 :(得分:1)
看起来你碰到了Ticket 2501。这已在主干中修复,您遇到的错误将来会更加清晰。