Python 使用twisted和greenlet时出错
我正在尝试将twisted与greenlets结合使用,这样我就可以在twisted中编写同步代码,而不必使用inlineCallbacks 这是我的密码:Python 使用twisted和greenlet时出错,python,twisted,greenlets,Python,Twisted,Greenlets,我正在尝试将twisted与greenlets结合使用,这样我就可以在twisted中编写同步代码,而不必使用inlineCallbacks 这是我的密码: import time, functools from twisted.internet import reactor, threads from twisted.internet.defer import Deferred from functools import wraps import greenlet def make_asyn
import time, functools
from twisted.internet import reactor, threads
from twisted.internet.defer import Deferred
from functools import wraps
import greenlet
def make_async(func):
@wraps(func)
def wrapper(*pos, **kwds):
d = Deferred()
def greenlet_func():
try:
rc = func(*pos, **kwds)
d.callback(rc)
except Exception, ex:
print ex
d.errback(ex)
g = greenlet.greenlet(greenlet_func)
g.switch()
return d
return wrapper
def sleep(t):
print "sleep(): greenelet:", greenlet.getcurrent()
g = greenlet.getcurrent()
reactor.callLater(t, g.switch)
g.parent.switch()
def wait_one(d):
print "wait_one(): greenelet:", greenlet.getcurrent()
g = greenlet.getcurrent()
active = True
def callback(result):
if not active:
g.switch(result)
else:
reactor.callLater(0, g.switch, result)
def errback(failure):
if not active:
g.throw(failure)
else:
reactor.callLater(0, g.throw, failure)
d.addCallback(callback)
d.addErrback(errback)
active = False
rc = g.parent.switch()
return rc
@make_async
def inner():
print "inner(): greenelet:", greenlet.getcurrent()
import random, time
interval = random.random()
print "Sleeping for %s seconds..." % interval
sleep(interval)
print "done"
return interval
@make_async
def outer():
print "outer(): greenelet:", greenlet.getcurrent()
print wait_one(inner())
print "Here"
reactor.callLater(0, outer)
reactor.run()
共有5个主要部分:
- 一个睡眠函数,启动计时器,然后切换回父greenlet。当计时器熄灭时,它会切换回正在睡觉的绿灯李>
- make_异步装饰器。这需要一些同步的代码,并在greenlet中运行。它还返回一个延迟消息,以便调用方可以在代码完成时注册回调李>
- 一个wait_one函数,它阻止greenlet,直到等待的延迟解决为止李>
- 内部函数(包装时)返回一个deferred,休眠一段随机时间,然后将休眠时间传递给deferred李>
- 调用inner()的外部函数等待它返回,然后打印返回值李>
outer():greenelet:
内部():greenelet:
睡眠0.545666723422秒。。。
sleep():greenelet:
等等,格林莱特:
完成
0.545666723422
在这里
异常twisted.python.failure.failure:处于忽略状态
绿色脱欧并没有造成死亡
通过一些研究,我发现:
- 最后一行由greenlet.c记录
- 前一行由python自己记录,因为它忽略了在del方法中引发的异常李>
GreenletExit
或twisted.python.failure.failure
异常以获取它们的堆栈跟踪
有人知道我做错了什么,或者我如何调试抛出的异常吗
另一个数据点:如果我hack wait_One()立即返回(并且不在延迟传递的数据上注册任何内容),错误就会消失-/ 在
wait\u one
中重写错误回调,如下所示:
def errback(failure):
## new code
if g.dead:
return
##
if not active:
g.throw(failure)
else:
reactor.callLater(0, g.throw, failure)
如果greenlet已停止运行(已完成运行),则抛出异常没有意义
在它里面。mguijarr的答案解决了这个问题,但我想写下我是如何陷入这种情况的 我有三个小菜:
- {main}反应堆正在运行李>
- {outer}正在运行outer()
- {inner}这是rrunning inner()
睡眠结束后,{main}切换到{inner},后者切换到{outer}。然后,Outer返回并在{inner}中引发GreenletExit。这又回到了扭曲。它看到回调()引发异常,因此调用errback()。这试图将异常抛出到{outer}(它已经退出)中,我发现了错误 这篇文章解释了,一旦您以这种方式隐式地调度协同路由,您就不再真正“使用Twisted”,因为您没有从它的编程模型中获得好处:-此外,您可能对已经这样做的库感兴趣,而不是编写自己的库-
def errback(failure):
## new code
if g.dead:
return
##
if not active:
g.throw(failure)
else:
reactor.callLater(0, g.throw, failure)