2016년 5월 20일 금요일

(python) decoration, thread & yield

작성 중...

1. decoration pattern, @ 사용.
호출부에서 read_batches(50) 시,

read_batches = mpgen(read_batches(50))

처럼 원 함수의 기능 확장.


2. python에서는 GIL문제로 thread 대신에 multiprocessing 사용.
mpgen을 통해 주 프로세스와는 별도의 데이터 생성 프로세스가 시작
Queue는 thread에서 데이터 공유에 사용(아래, 최대 3개까지의 item 저장 가능)


3. yield
함수의 형태를 가지는 iterator (generator, 생성기라고 부름)를 만들어 줌.
iterator란?
c = iter(range(5))
c.next(), c.next(),... # 0,1,2,...

함수의 인자를 비휘발성으로 만듬
함수 재호출 시, yield 다음이 수행
return은 결과값 반환, yield는 iterator 반환


4. functools.wraps:
디버깅 시 func.__doc__ 또는 func.__name__ 등의 속성을 요청 시
원 함수 read_batches의 속성이 안나오고 decoration된 mpgen함수의 속성이 나오는 것을 방지.
함수 속성을 인자인 원 함수 f로 되돌리는 역할.
데코레이터에서 closure문제 해결을 위해 사용.



def mpgen(f):
    def main(q, args, kwargs):
        try:
            for item in f(*args, **kwargs):
                q.put(item)
        finally:
            q.close()

    @functools.wraps(f) 
    def wrapped(*args, **kwargs): #*args(리스트 받고), **kwargs(map 받음)
        q = multiprocessing.Queue(3)
        proc = multiprocessing.Process(target=main, args=(q, args, kwargs))
        proc.start()
        try:
            while True:
                item = q.get()
                yield item
        finally:
            proc.terminate()
            proc.join()

    return wrapped
     

@mpgen # mpgen의 인자함수로 read_batches을 사용함을 지정
def read_batches(batch_size):
    def gen_vecs():
        for im, c, p in gen.generate_ims(batch_size):
            yield im, code_to_vec(p, c)

    while True:
        yield unzip(gen_vecs()) # yield는 휘발성이 없는 함수(iterator 만듬)


댓글 없음:

댓글 쓰기