2013-10-26 3 views
1

필자는 꼬인 꼬챙이를 그린렛으로 사용하려고하므로 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()을 해킹하여 즉시 반환하기 만하면 (지연된 데이터를 등록하지 않고 전달하면) 오류가 사라집니다. : -/

+0

이 기사에서는 coroutines를 암시 적으로 이런 식으로 예약하면 어떻게하면 프로그래밍 모델의 이점을 얻지 못한다는 의미에서 더 이상 "Twisted"를 사용하지 않는지 설명합니다. https : // glyph. twistedmatrix.com/2014/02/unyielding.html - 또한 직접 작성하지 않고 이미이 작업을 수행하는 라이브러리에 관심이있을 수 있습니다. - https://github.com/radix/corotwine – Glyph

답변

2
이 같은 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 죽은 (완료 실행)의 경우, 포인트 던지는 예외에게 그것에 없다.

+0

감사합니다. 매력처럼 :-). –

0

mguijarr의 대답으로 문제가 해결되었지만이 상황에 어떻게 대처했는지 기록하고 싶습니다.

  • 가 {주} 즉 원자로를들이받은 것 :

    나는 세 greenlets 있습니다.

  • {outer}이 (가) 외부를 실행 중입니다.
  • {inner}이 (가) rrunning inner()입니다.

수면이 끝나면 {메인}이 {내부}로 전환하여 {외부}로 전환됩니다. 그런 다음 외부는 {inside}에서 GreenletExit을 반환하고 올립니다. 이것은 뒤틀린 상태로 되돌아 간다. callback()에서 발생한 예외를보고 errback()을 호출합니다. 이것은 (이미 종료 된) {outer}에 예외를 던지려고 시도하며 오류가 발생했습니다.