gpt4 book ai didi

python - 使用 Twisted 和 Greenlet 时出错

转载 作者:行者123 更新时间:2023-12-01 05:33:45 24 4
gpt4 key购买 nike

我正在尝试将twisted与greenlet一起使用,这样我就可以在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_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个部分:

  • sleep 函数,启动计时器,然后切换回父 greenlet。当计时器关闭时,它会切换回正在休眠的 greenlet。
  • 一个 make_async 装饰器。这需要一些看起来同步的代码并在 greenlet 中运行它。它还返回一个延迟,以便调用者可以在代码完成时注册回调。
  • wait_one 函数,它会阻塞 greenlet,直到等待的延迟解决。
  • 内部函数(当包装时)返回一个 deferred,休眠随机时间,然后将其休眠的时间传递给 deferred。
  • 外部函数调用inner(),等待它返回,然后打印返回值。

当我运行此代码时,我得到以下输出(请注意最后两行的错误):

outer(): greenelet: <greenlet.greenlet object at 0xb729cc5c>
inner(): greenelet: <greenlet.greenlet object at 0xb729ce3c>
Sleeping for 0.545666723422 seconds...
sleep(): greenelet: <greenlet.greenlet object at 0xb729ce3c>
wait_one(): greenelet: <greenlet.greenlet object at 0xb729cc5c>
done
0.545666723422
Here
Exception twisted.python.failure.Failure: <twisted.python.failure.Failure <class 'greenlet.GreenletExit'>> in <greenlet.greenlet object at 0xb729ce3c> ignored
GreenletExit did not kill <greenlet.greenlet object at 0xb729ce3c>

做了一些研究,我发现:

  • 最后一行由 greenlet.c 记录
  • 前一行由 python 本身记录,因为它忽略 del 方法中引发的异常。

我在调试此问题时遇到了真正的麻烦,因为我无法访问 GreenletExittwisted.python.failure.Failure 异常来获取其堆栈跟踪。

有人知道我做错了什么,或者我如何调试抛出的异常吗?

另一个数据点:如果我破解 wait_one() 立即返回(而不是在传递的延迟上注册任何内容),错误就会消失。 :-/

最佳答案

wait_one 中重写错误回调,如下所示:

  def errback(failure):
## new code
if g.dead:
return
##
if not active:
g.throw(failure)
else:
reactor.callLater(0, g.throw, failure)

如果 greenlet 死了(完成运行),则没有必要抛出异常就在其中。

关于python - 使用 Twisted 和 Greenlet 时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19604921/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com