필자는 꼬인 꼬챙이를 그린렛으로 사용하려고하므로 inlineCallbacks를 사용하지 않고 꼬인 상태로 동기식 코드를 작성할 수 있습니다. 다음, 타이머를 시작트위스트와 그린렛을 사용할 때의 에러
- 잠 기능, 부모 greenlet로 다시 전환 :
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 개 가지 주요 부분이 있습니다
여기 내 코드입니다. 타이머가 꺼지면 잠 들어있는 녹색 머리로 다시 전환됩니다.
- make_async 데코레이터. 이것은 동기식으로 보이는 코드를 가져 와서 greenlet에서 실행합니다. 또한 IT는 코드를 완료 할 때 호출자가 콜백을 등록 할 수 있도록 지연을 반환합니다.
- wait_one 함수는 해결시 대기 상태가 될 때까지 greenlet을 차단합니다.
- (wrapped 일 때) 내부 함수는 지연을 반환하고, 임의의 시간 동안 잠자기 한 다음, 잠자기 시간을 지연된 것으로 전달합니다.
- 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에 의해 로그됩니다.
- 메소드에서 발생한 예외를 무시하므로 이전 라인은 파이썬 자체에 의해 로그됩니다.
나는 진짜 문제 내가 그들의 스택 추적을 얻을 수있는 GreenletExit
또는 twisted.python.failure.Failure
예외에 액세스 할 수있는이 디버깅하는 데 문제가 있습니다.
누구나 내가 뭘 잘못하고있는 아이디어가 있습니까? 또는 던져진 예외를 어떻게 디버그합니까?
다른 하나의 데이터 요소 : wait_one()을 해킹하여 즉시 반환하기 만하면 (지연된 데이터를 등록하지 않고 전달하면) 오류가 사라집니다. : -/
이 기사에서는 coroutines를 암시 적으로 이런 식으로 예약하면 어떻게하면 프로그래밍 모델의 이점을 얻지 못한다는 의미에서 더 이상 "Twisted"를 사용하지 않는지 설명합니다. https : // glyph. twistedmatrix.com/2014/02/unyielding.html - 또한 직접 작성하지 않고 이미이 작업을 수행하는 라이브러리에 관심이있을 수 있습니다. - https://github.com/radix/corotwine – Glyph