본문 바로가기

카테고리 없음

파이썬 표준 라이브러리(multiprocession, Pickle)

multiprocessing

이 모듈은 여러 프로세스를 생성, 병렬처리할 때 싸용한다. 컴퓨터가 작업을 효율적으로 하는데 도움을 준다.

 

언제 쓰는가? 주요 사례를 위주로 살펴보자 !

 

1. 기본 Process 생성-실행

from multiprocessing import Process

def process1_function():
    print("프로세스 실행 중")

if __name__ == '__main__':
    process = Process(target=process1_function)
    process.start()
    process.join()  # 프로세스가 종료될 때까지 기다림

Process라는 클래스를 사용하면 현재 프로세스, 그리고 별도의 다른 프로세스에서 함수-메서드를 실행할 수 있게 해준다.

target이라는 매개변수에는 별도의 프로세스에서 실행할 함수를 지정한다. (지금 이 상황에서는 process1~함수가 지정)

 

그래서 Process라는 클래스를 선언한다면, 계속해서 새로운 프로세스를 생성할 수 있게 되는 것임. (병렬작업 가능)

 

 

 

 

 

2. 여러 Process 사용

 

from multiprocessing import Process

def work(id):
  print(f"Process {id} working...")

processes = [Process(target=work, args=(i,)) for i in range(3)]
for p in processes:
  p.start()
for p in processes:
  p.join()

이번에 나온 이 Process에는 work라는 함수를 대상으로 한다.

그리고 각 프로세스에는 인덱스 i를 args, 인자로 전달한다.

매개변수로는 튜플 (i,)를 전달한다. 

 

 

 

3. 데이터 공유 (Value, Array 사용)

 

여러개의 프로세스가 진행되는동안, 데이터를 공유할 수도 있다. 

 

from multiprocessing import Process, Value, Array

number = Value('i', 0)
array = Array('i', range(5))

def add_one(number, array):
  number.value += 1
  for i in range(len(array)):
    array[i] += 1

processes = [Process(target=add_one, args=(number, array)) for _ in range(2)]

for p in processes:
  p.start()
for p in processes:
  p.join()
print(f"number : {number.value}")
print(f"array : {list(array)}")

 

여기에서 add_one이라는 함수로 먼저 가보자. 이 함수는 number라는 Value객체 Array라는 공유 배열을 인자로 받는다. 

그리고 함수 안에서, number안의 value에 1을 먼저 더하고 array의 각 요소에 1을 더하라고 명령한다. 

 

number의 Value는 초기값이 0인 정수형이다.

array는 0부터 4까지의 정수로 이루어진 배열이다. (list나 set으로 담으면 값을 출력해준다.)

 

중간의 for _ in range(2)는 보통 쓰는 중간변수 대신 '_'를 사용했다. 이렇게 하면 반복문을 2번 반복하는데, 반복 중 range(2)에 따라 바뀌는 값을 사용하지 않게된다. (반복되는 값 안쓰고 버림 여기서는 0과 1)

 

 

 

 

 

4. Pool을 사용한 병렬 처리

 

from multiprocessing import Pool

def square1(n):
  return n**2

with Pool(3) as p:
  results = p.map(square, range(10))
results

여기서, square1 함수는 들어온 숫자의 제곱을 반환한다. 

with문을 통해서 Pool 객체를 생성한다. Pool(3)은 3개의 프로세스를 가지는 프로세스 풀을 생성한다는 의미다. 

 

Pool 객체는 map()메서드가 있는데, 이것을 통해서 주어진 함수(square)를 주어진 데이터(range(10))에 대해서 병렬로 적용한다. 

Pool을 쓰면 여러 프로세스를 동시에 실행해서 작업을 병렬로 처리할 수 있다 !!

 

 

 

 

 

 

 

 

pickle

pickle모듈은 파이썬 객체를 직렬화(serialize)하거나 역직렬화(deserialize)하는데 사용되는 모듈이다.

이 모듈은 파이썬의 객체를 파일이나 네트워크로 전송-저장하기 위해서 사용된다. 

 

*직렬화 - 객체나 데이터 구조를 메모리에서 저장-전송 할 수 있는 형식으로 변환하는 과정. 이 과정에서 객체나 데이터 구조는 바이트스트림(byte stream) 또는 텍스트(text) 형식으로 변환된다. 그래서 직렬화된 데이터는 파일로 저장하거나 네트워크를 통해서 전송할 수 있다. 

*역직렬화 - 직렬화된 데이터를 다시 객체나 데이터 구조로 복원하는 과정. 직렬화된 byte stream이나 text 데이터를 읽어와서 원래의 객체나 데이터 구조로 변환하는 것.

 

 

객체 직렬화 (저장)

import pickle

data = {'a':[i for i in range(12)],
        'b':list("Hello World!"),
        'c':{True, False},
        'i':["InnovationPARK here!"]
        }
        
        
with open('data.pickle', 'wb') as f:
    pickle.dump(data, f)
  
  
with open('data.pickle', 'rb') as f:
    data1 = pickle.load(f)
    
class A:
	name='good'
    
a = A()

with open('a.pickle', 'wb') as f:
    pickle.dump(a, f)

with open('a.pickle', 'rb') as f:
    aa = pickle.load(f)


aa.name

 

먼저 딕셔너리를 정의함. 여기엔 다양한 유형의 데이터가 담김.

 

with + pickle.dump() - data를 'data.pickle'이라는 이름으로 저장

with + pickle.load() - data1이라는 변수가 중요함. 이 변수는 data.pickle로 방금 저장한 데이터를 읽어와서 역직렬화하여 저장해주는 역할을 함.

 

뒷부분에 나오는 내용

with + pickle.dump() - a객체를 a.pickle이라는 이름으로 직렬화하여 저장.(인스턴스도 저장가능)

with + pickle.load() - 마찬가지로 'a.pickle' 파일에서 직렬화한 데이터를 읽어와서 역직렬화, aa라는 데이터에 담음.

aa.name을 통해 aa라는 것은 name이라는 속성을 가진 객체라는 것을 알 수 있음.

실제로 aa.name의 출력 결과는 'good'

 

*with문 안에 있는 'wb'와 'rb' 

  • 'wb': 이진 쓰기 모드(Binary Write Mode). 파일을 이진 형식으로 열어 쓰기 작업을 수행. 이 모드로 열린 파일은 텍스트가 아닌 이진 데이터를 쓰기 위해 사용됨.
  • 'rb': 이진 읽기 모드(Binary Read Mode). 파일을 이진 형식으로 열어 읽기 작업을 수행. 이 모드로 열린 파일은 이진 데이터를 읽기 위해 사용됨.