Python eventlet

원본 주소:http://www.cnblogs.com/Security-Darren/p/4168233.html http://www.2cto.com/net/201610/553556.html http://blog.csdn.net/gaoxingnengjisuan/article/details/12913275
이벤트 let 는 python 라 이브 러 리 함수 입 니 다. 하 나 는 네트워크 와 관련 된 처리 이 고 다른 하 나 는 협 정 을 통 해 병행 할 수 있 습 니 다.병발 이란 여러 개의 greenthread (녹색 스 레 드) 를 열 고 이 greenthread 를 관리 하여 비 차단 식 I / O 를 실현 하 는 것 이다.이벤트 let 는 '녹색 스 레 드' 를 실현 하기 위해 python 의 네트워크 와 관련 된 몇 개의 표준 라 이브 러 리 함 수 를 바 꾸 었 고 패 치 (patch) 방식 으로 프로그램 에 가 져 올 수 있 습 니 다. python 의 라 이브 러 리 함 수 는 일반적인 스 레 드 만 지원 하고 협 의 를 지원 하지 않 기 때문에 이벤트 let 는 '녹화' 라 고 부 릅 니 다.
본 고 는 먼저 Greenlet, GreenThread 를 설명 한 다음 에 eventlet 에서 자주 사용 하 는 몇 가지 유형 을 설명 한다.
GreenLet
greenlet 은 협 정 (coroutine) 이 라 고 불 리 는 물건 으로 다음 과 같은 몇 가지 특징 이 있다.1. 모든 협 정 은 자신의 개인 stack 과 부분 변 수 를 가진다.2. 같은 시간 에 하나의 협정 만 운행 되 기 때문에 일부 공유 변수 에 자 물 쇠 를 채 울 필요 가 없다.3. 협 정 간 의 집행 순 서 는 절차 에 의 해 제어 된다.한 마디 로 하면 협 정 은 한 스 레 드 에서 실행 되 는 의사 병행 방식 으로 최종 적 으로 하나의 협 정 만 운행 한 다음 에 프로그램 이 집행 순 서 를 제어 하 는 것 이다.아래 의 예 를 보고 위의 뜻 을 이해 할 수 있다.
import greenlet  

def test1(n):  
    print "test1:",n  
    gr2.switch(32)  
    print "test1: over"  

def test2(n):  
    print "test2:",n  
    gr1.switch(23)  
    print "test2: over"  

greenlet = greenlet.greenlet  
current = greenlet.getcurrent()  
gr1 = greenlet(test1,current)  
gr2 = greenlet(test2,current)  
gr1.switch(2)  

이 프로그램의 실행 결 과 는 다음 과 같다.
test1: 2  
test2: 32  
test1: over  

전체 프로그램의 과정 은 매우 직 설 적 입 니 다. 먼저 두 개의 협 정 을 만 들 고 생 성 하 는 과정 은 실행 할 함수 와 부모 greenlet (앞에서 제시 한 세 개의 링크 에 상세 한 소개 가 있 습 니 다) 에 들 어간 다음 에 그 중의 한 협 정의 switch 함 수 를 호출 하고 매개 변 수 를 전달 하 며 test 1 을 실행 한 다음 에 gr2. switch (32) 문 구 를 통 해 test 2 함수 로 전환 합 니 다.마지막 에 다시 돌려.최종 test 1 실행 이 끝나 면 부모 greenlet 으로 돌아 가 실행 이 끝 납 니 다.이 과정 은 시종일관 하나의 협정 만 운행 하고 함수 의 집행 흐름 은 프로그램 스스로 제어 하 는 것 이다.이 과정 은 위의 링크 에서 더욱 구체 적 으로 묘사 되 었 다.
참고 자료:http://greenlet.readthedocs.org/en/latest/
GreenThread
그러면 이벤트 let 에서 greenlet 에 대해 간단 한 패 키 징 을 하면 GreenThread 가 되 고 위의 프로그램 에 문제 가 생 길 수 있 습 니 다. 만약 에 우리 가 협 정 을 쓰 려 면 함수 의 집행 과정 을 어떻게 통제 해 야 하 는 지, 협 정 이 많 으 면 통제 가 복잡 하지 않 습 니까?이 문 제 를 가지 고 이벤트 let 의 실현 을 보다.
이벤트 Let 에서 GreenThread 의 스케줄 링 은 hub 를 통 해 이 루어 집 니 다.hub 는 EventLet 의 시간 순환 으로 IO 이벤트 와 GreenThread 를 조정 합 니 다.Hub 는 epolls, poll, selects, pyevent 버 전 등 다양한 버 전의 구현 이 있 습 니 다.http://eventlet.net/doc/hubs.html#eventlet.hubs.use_hub)。이벤트 let. hubs. use 사용 가능hub (hub = None) 는 사용 하 는 hub 를 설정 합 니 다. 그 중에서 들 어 오 는 매개 변 수 는 선택 한 hub 의 이름 입 니 다.
hub 는 스 레 드 국 의 인 스 턴 스 입 니 다. 즉, 모든 스 레 드 에 hub 가 있 습 니 다. 이 스 레 드 의 co - rountine 스케줄 을 관리 하 는 데 사 용 됩 니 다.모든 스 레 드 에 적합 한 hub 를 선택 할 수 있 습 니 다.
hub 작업 원리: hub 는 자체 적 으로 GreenLet 을 가지 고 있 습 니 다. MainLoop 입 니 다. 실행 중인 coroutine 이 IO 작업 이 필요 할 때 이 co - routine 은 hub 에 모니터 를 등록 합 니 다 (hub 는 언제 co - routine wake up 을 알 고 있 습 니 다).다른 실행 가능 한 co - routine 이 있 으 면 hub MainLoop 은 이 co - routine (via get hub (). switch () 로 전환 합 니 다.이 co - routime 이 완성 되 었 거나 IO 가 필요 하 다 면 hub main Loop 으로 전환 합 니 다.이렇게 하면 모든 co - rountine 이 배 치 될 수 있 도록 보장 합 니 다.
hub MAINLOOP 은 첫 번 째 IO 작업 에서 시 작 됩 니 다.이 lazy 모드 는 디 스 패 치 함 수 를 표시 하지 않 아 도 됩 니 다.
이벤트 let 공식 문서 (http://eventlet.net/doc/basic_usage.html)
GreenPool
이 모듈 은 greenthread 풀 에 대한 지원 을 제공 합 니 다.
greenthread 탱크 는 일정한 수량의 예비 greenthread 를 제공 하여 부화 greenthread 가 너무 많아 서 발생 하 는 메모리 부족 을 효과적으로 제한 합 니 다. 연못 에 충분 한 여유 가 없 을 때 부화 과정 이 중단 되 고 이전 작업 중의 greenthread 가 현재 작업 을 완성 해 야 다음 작업 에 부화 준 비 를 할 수 있 습 니 다.
class eventlet. greenpool. GreenPool (size = 1000) 클래스 의 주요 방법: 1. free ()
  2. imap(function, *iterables)
  3. resize(new_size)
  4. running()
  5. spawn(function, *args, **kwargs)
  6. spawn_n(function, *args, **kwargs)
  7. starmap(function, iterable)
  8. waitall()
9. waiting () 1. free (): 현재 대상 에서 사용 할 수 있 는 greenthreads 를 되 돌려 줍 니 다.
0 또는 더 적 으 면 spawn () 과 spawnn () 은 새로운 사용 가능 한 greenthread 가 있 을 때 까지 greenthread 호출 을 막 을 것 입 니 다.
이 곳 에서 마이너스 값 을 되 돌 릴 수 있 는 이 유 는 3. resize () 2. imap (function, * iterables) 를 보십시오. 효 과 는 itertools. imap () 와 같 고 병발 과 메모리 사용 에 있어 서 starmap () 과 같 습 니 다.
예 를 들 어 파일 에 대해 매우 편리 하 게 조작 할 수 있다.
def worker(line):
    return do_something(line)
pool = GreenPool()
for result in pool.imap(worker, open("filename", 'r')):
    print(result)
  • resize (new size): 현재 동시에 작업 할 수 있 는 greenthreads 최대 수량 변경
  • 현재 new 보다 많 으 면size 의 greenthreads 는 업무 중 에 있 습 니 다. 그들 은 자신의 집행 을 완성 할 수 있 습 니 다. 다만 이 때 는 새로운 greenthreads 가 분배 되 는 것 을 허락 하지 않 습 니 다.충분 한 수량의 greenthreads 가 자신의 일 을 완성 한 후에 작업 중의 greenthreads 총수 가 new 보다 낮 습 니 다.size 시 새로운 greenthreads 가 분 배 됩 니 다.그 전에 free () 의 반환 값 은 마이너스 가 됩 니 다.
  • running (): 현재 연못 에서 작업 을 수행 하고 있 는 greenthreads 를 되 돌려 줍 니 다.
  • spawn (function, * args, * * kwargs): 현재 연못 에서 사용 가능 한 greenthread 를 부화 시 켜 이 greenthread 에서 function 을 실행 합 니 다. 매개 변수 * args, * kwargs 는 function 에 전 달 된 매개 변수 입 니 다.GreenThread 대상 을 되 돌려 줍 니 다. 이 대상 은 function 을 실행 하고 있 습 니 다. 이 GreenThread 대상 을 통 해 function 의 반환 값 을 가 져 올 수 있 습 니 다.현재 연못 에 남 은 greenthread 가 없다 면 이 방법 은 새로운 사용 가능 한 greenthreads 가 풀 려 날 때 까지 막 습 니 다.이 함 수 는 다시 사용 할 수 있 습 니 다. function 은 같은 GreenPool 대상 의 spawn 방법 을 호출 할 수 있 습 니 다. 잠 금 걱정 은 하지 마 세 요.
  • spawn_n (function, * args, * * kwargs): greenthread 를 만들어 function 을 실행 합 니 다. 효 과 는 spawn () 과 같 습 니 다.다만 이 함 수 는 None, 즉 function 의 반환 값 을 버 립 니 다.
  • starmap (function, iterable): itertools. starmap () 과 같 습 니 다. 교체 가능 한 대상 의 모든 요 소 를 제외 하고 하나의 greenthread 에서 func 를 실행 합 니 다.병발 의 상한 선 은 연못 의 용량 에 의 해 제한 된다.실제 작업 에서 starmap () 이 소모 하 는 메모리 와 연못 의 용량 이 비례 하여 특히 긴 입력 목록 을 옮 겨 다 니 기 에 적합 합 니 다.
  • waitall() ;연못 에 있 는 모든 greenthreads 가 일 을 완성 하 기 를 기다 리 고 있 습 니 다.
  • waiting (): 현재 부 화 를 기다 리 고 있 는 greenthreads 수 를 되 돌려 줍 니 다.

  • GreenPile
    class eventlet. greenpool. GreenPile (size or pool = 1000) 는 내부 에서 GreenPool 대상 과 Queue 대상 을 유지 합 니 다.이 GreenPool 대상 은 외부 에서 전 달 될 수도 있 고 클래스 내부 에서 만 들 수도 있 습 니 다. GreenPool 대상 은 주로 녹색 스 레 드 를 만 드 는 데 사 용 됩 니 다. 즉, GreenPile 내부 에서 Greenpool. spawn () 방법 을 호출 했 습 니 다.Queue 대상 은 spawn () 방법의 반환 값 을 유지 하 는 데 사 용 됩 니 다. 즉, Queue 에 저 장 된 것 은 GreenThread 대상 입 니 다.또한 next () 방법 도 실현 했다 는 것 은 GreenPile 대상 이 교체 기의 성질 을 가지 고 있다 는 것 을 의미한다.그래서 만약 에 우리 가 녹색 스 레 드 의 반환 값 을 조작 하려 면 이런 종 류 를 사용 하 는 것 이 더 할 나 위 없 이 좋다.
    Event
    class eventlet. event. Event Event: 같은 라인 에서 의 협정 통신 메커니즘 (an arbitrary number of coroutines can wait for one event from another).Event 와 Queue 형식 은 하나의 메시지 만 수용 할 수 있 는 Queue 로 볼 수 있 습 니 다. 그러나 Queue 와 다른 것 은: (1) send () 를 호출 하면 현재 greenthread 에 대한 예약 을 취소 하지 않 습 니 다.(2) 이벤트 인 스 턴 스 에 대해 send 함 수 를 한 번 만 호출 할 수 있 습 니 다.만약 당신 이 두 개의 메 시 지 를 보 낼 필요 가 있다 면, 두 개의 이벤트 대상 이 필요 합 니 다.사용 실례:
    from eventlet import event
    import eventlet
    evt = event.Event()
    def baz(b):
         evt.send(b + 1)
     _ = eventlet.spawn_n(baz, 3)
     evt.wait()  

    함수 설명: 1. ready (): 이벤트 대상 이 이 벤트 를 보 낸 적 이 있 는 지 판단 합 니 다. wait () 를 호출 하면 이벤트 결 과 를 즉시 되 돌려 줍 니 다. 그러면 이 곳 에서 실제 값 을 되 돌려 줍 니 다.그 방법 은 한동안 기 다 려 야 발생 하 는 사건 을 피 하 는 데 쓰 인 다.예 를 들 어 하나의 이벤트 들 을 Python 목록 에 넣 고 반복 해서 옮 겨 다 닐 수 있 습 니 다. 이것 은 ready () 를 사용 하여 하나의 이벤트 가 True 로 돌아 갈 때 까지 즉시 wait () 를 호출 하여 가 져 올 수 있 습 니 다.2. send (result = None, exc = None): 이 벤트 를 보 내 면 다른 wait 의 협 정 을 깨 울 수 있 습 니 다.이 방법 을 호출 하 는 협 정 은 즉시 돌아 갑 니 다 (막 히 지 않 습 니 다)
    >>> from eventlet import event
    >>> import eventlet
    >>> evt = event.Event()
    >>> def waiter():
    ...     print('about to wait')
    ...     result = evt.wait()
    ...     print('waited for {0}'.format(result))
    >>> _ = eventlet.spawn(waiter)
    >>> eventlet.sleep(0)
    about to wait
    >>> evt.send('a')
    >>> eventlet.sleep(0)
    waited for a

    주의해 야 할 것 은 같은 이벤트 인 스 턴 스 에 여러 번 send 함 수 를 호출 하면 이상 을 던 질 수 있 습 니 다.
    >>> evt.send('whoops')
    Traceback (most recent call last):
    ...
    AssertionError: Trying to re-send() an already-triggered event.
  • send_exception (* args): send () 방법 과 유사 한 역할 을 하 며 대기 자 에 게 만 이상 을 보 냅 니 다.하나의 이상 대상 이 들 어 오 면 wait () 방법 이 호출 될 때 다시 던 져 새로운 스 택 궤적 을 만 듭 니 다.
  • >>> from eventlet import event
    >>> evt = event.Event()
    >>> evt.send_exception(RuntimeError())
    >>> evt.wait()
    Traceback (most recent call last):
      File "", line 1, in <module>
      File "eventlet/event.py", line 120, in wait
        current.throw(*self._exc)
    RuntimeError

    스 택 궤적 을 완전 하 게 유지 하려 면 sys. exc 전체 에 전송 해 야 합 니 다.info () 모듈. 
    >>> import sys
    >>> evt = event.Event()
    >>> try:
    ...     raise RuntimeError()
    ... except RuntimeError:
    ...     evt.send_exception(*sys.exc_info())
    ...
    >>> evt.wait()
    Traceback (most recent call last):
      File "", line 1, in 
      File "eventlet/event.py", line 120, in wait
        current.throw(*self._exc)
      File "", line 2, in 
    RuntimeError

    이벤트 대상 내부 에 traceback 대상 을 저장 합 니 다. 이 는 순환 참조 로 이 어 질 수 있 습 니 다.sys. exc 참조info () 문서 입 니 다.
  • wait (): 다른 협 정 이 send () 를 호출 할 때 까지 기 다 립 니 다.다른 협 정 이 send () 방법 에 전달 하 는 값 을 되 돌려 줍 니 다.
  • >>> from eventlet import event
    >>> import eventlet
    >>> evt = event.Event()
    >>> def wait_on():
    ...    retval = evt.wait()
    ...    print("waited for {0}".format(retval))
    >>> _ = eventlet.spawn(wait_on)
    >>> evt.send('result')
    >>> eventlet.sleep(0)
    waited for result

    참고:http://eventlet.net/doc/modules/event.html http://www.cnblogs.com/Security-Darren/p/4168116.html
    예 를 들다
    1. 인터넷 파충류, 녹색 스 레 드 탱크 로 urls 의 정 보 를 얻 습 니 다.녹색 스 레 드 탱크 와 imap () 함 수 를 사용 합 니 다.
    import eventlet
    from eventlet.green import urllib2
    
    
    urls = [
        "http://www.google.com/intl/en_ALL/images/logo.gif",
        "https://wiki.secondlife.com/w/images/secondlife.jpg",
        "http://us.i1.yimg.com/us.yimg.com/i/ww/beta/y3.gif",
    ]
    
    
    def fetch(url):
        return urllib2.urlopen(url).read()
    
    
    pool = eventlet.GreenPool(200) #         ,      
    
    for body in pool.imap(fetch, urls): #                  url   
        print("got body", len(body))

    2, socket 서버
    import eventlet
    
    def handle(fd):
        print "client connected"
        while True:   #          
            # pass through every non-eof line  
            x = fd.readline()
            if not x: break
            fd.write(x)
            fd.flush()         #           
            print "echoed", x,
        print "client disconnected"
    
    
    print "server socket listening on port 8000"   #       ,          
    server = eventlet.listen(('127.0.0.1', 8000))  # (IP  ,   )        
    pool = eventlet.GreenPool(200)    #     ,      
    
    while True:
            new_sock, address = server.accept() #  ,            socket         IP      
            print "accepted", address
            pool.spawn_n(handle, new_sock.makefile('rw'))  #             

    3. GreenPile 을 사용 한 예
    import eventlet
    from eventlet.green import socket
    
    def geturl(url):
        c = socket.socket()
        ip = socket.gethostbyname(url)
        c.connect((ip, 80))
        print '%s connected' % url
        c.sendall('GET /\r
    \r
    '
    ) return c.recv(1024) urls = ['www.google.com', 'www.yandex.ru', 'www.python.org'] pile = eventlet.GreenPile() for x in urls: pile.spawn(geturl, x) # note that the pile acts as a collection of return values from the functions # if any exceptions are raised by the function they'll get raised here for url, result in zip(urls, pile): print '%s: %s' % (url, repr(result)[:50])

    좋은 웹페이지 즐겨찾기