Python/2.7 information

general function for multiprocessing

qkqhxla1 2018. 10. 17. 19:20

코딩을 하다 보면 특정 클래스의 특정 함수를 멀티프로세스로 돌려야할 경우가 생긴다. 매번 그냥 main안에 프로세스를


만들고 start()를 하고, join까지 넣었는데 이것들을 예쁘게 감싸줄 필요성을 느껴서 만들었다.

# -*- coding: utf-8 -*-

from multiprocessing import Process
import time

class MultiProcessTest:
    # example_function을 multiprocessing으로 돌리고 싶다.
    def example_function(self, kwargs):
        ps_order = kwargs['order']
        parameter = kwargs['parameter']
        while True:
            print '{} {} in example function!!'.format(ps_order, parameter)
            time.sleep(2)
            # break

def execute_function_several_process(function, **kwargs):
    process_list = []
    for i in xrange(kwargs.pop('ps_num', 1)):
        kwargs['order'] = i
        n = function.im_class()
        ps = Process(target=getattr(n, function.__name__), args=(kwargs, ))
        ps.start()
        process_list.append(ps)
    
    for ps in process_list:
        ps.join()

ps_num = 4
if __name__ == '__main__':
    execute_function_several_process(MultiProcessTest.example_function, ps_num=ps_num, parameter='parameter~')
가볍게 좀 생각하면서 만들어봤는데.. execute_function_several_process함수의 첫번째 인자로 저렇게 받는 이유는

1. 스트링보다는 저렇게 객체화?로 보내야 덜 에러가 날것같아서였다. (대부분 ide를 사용하니까 저렇게 자동완성으로 만들어지는걸 사용시 오타율이 줄어든다?)

2. 저렇게 함수형태로 보내면 다시 execute~함수 내에서 원본 클래스를 편하게 가져올 수 있다.(function.im_class)


프로세스를 만들때 매번 인스턴스를 새로 생성해주는 이유는 특정 모듈들이 하나의 인스턴스에서 함수만 멀티프로세스로 분화할 경우 연결이 끊어지는 경우가 있어서이다.


인자 전달을 좀 고민해봤는데 저렇게 밖에서 전부 **kwargs로 받고 execute_~함수에서 사용할 인자들은 pop으로 딕셔너리에서 제거해준다. 그리고 남는 인자들을 원래 호출하려 했던 함수에 다시 그대로 넘겨주면 내부 함수에서는 내부 함수에 필요한 인자만 받게 되므로 받아서 사용하면 된다.


사실 내가 필요한 대부분의 요구사항은 만족하나 뭔가 부족한 느낌이 든다. 인자전달이 뭔가 깔끔하지 못한점 등.. 

그래도 이렇게 general하게 만들려고 삽질을 하면서 조금 공부가 된것 같다. 

그리고 애매하게 몰랐던건데 프로세스 안에서 다시 프로세스를 여러개 만들어도 main에서 프로세스 만든것과 동일하게 동작한다.