본문 바로가기
Programming/Python

파이썬 바이너리 파일 입출력 struct와 pickle

by whitele 2021. 9. 25.
반응형

 바이너리 파일 입출력은 저수준 방식의 파일 입출력을 사용하는 방법입니다. 바이트 열을 다루게 됩니다. 기본적으로 텍스트 파일 입출력과 사용방법이 동일합니다. 옵션에 바이너리 모드인 것을 명시해주면 됩니다. 

with open('s.txt','wb') as ori:
    ori.write(b'1234')

 바이너리 데이터를 다루기 위해서 struct, pickle 패키지 등의 패키지를 알게 되면 다루기가 수월합니다. 바이너리를 다루는 만큼 저수준 데이터를 다루므로 운영체제, 시스템, 언어에 대한 이해도가 있으면 좋습니다.

struct 패키지

 파이썬으로 다루지 않은 바이너리 파일을 다루려면 struct 패키지를 사용하는 것이 좋습니다. 바이트 문자열로 pack, unpack 함수가 있습니다. c의 구조체 형식으로 저수준으로 바이너리를 packing 혹은 unpacking 합니다. struct 패키지를 사용하기 위해선 import struct를 해야 합니다.

 구조체로 변환을 위해서 먼저 파이썬 문자열을 byte 문자열로 변환해야 합니다. packing 할 경우 문자열 클래스의 encode 메서드, 반대로 unpacking의 경우 decode를 사용할 수 있습니다.

 

 

struct 메서드

pack

byte_str=struct.pack(type,value1,value2,...)

pack 함수는 데이터 타입과 1개 이상의 값을 인자로 받습니다. c구조체 형식으로 변환합니다.

unpack

value_arr = struct.unpack(type,byte_str)

 unpack 함수는 데이터 타입과 바이트 문자열을 인자로 받는다. c구조체 형식에서 배열로 변환합니다.

calcsize

 파이썬 문자열이 요구하는 바이트를 반환합니다.

 

타입 지시자 종류

타입 지시자 c언어 자료형 크기
c char 1
? bool 1
(H) h (unsigned)short 2
(L) l (unsigned) long 4
(Q) q (unsigned) longlong 8
f float 4
d double 8
ints char* *
p 파스칼언어  

struct 메서드를 사용하기 위해서는 어떤 타입의 구조체로 저장할지 지정해야 합니다.

 

import struct

def packing(file_name, str):
	with open(file_name, 'wb') as file:
        	fmt='l'+str(len(str))+'s'
        	bss = pack(fmt, n, str.encode('utf-8'))
        	f.write(bss)
        
        
def unpacking(file_name):
	with open(file_name, 'rb') as file:
    		bss = f.read(calcsize('l')
        	n = unpack('l', bss)
        	bss = f.read(n)

 

 

빅 엔디안 & 리틀 엔디안

 저수준의 파일을 다루기 때문에 엔디안에 대한 이해도가 필요합니다. 쉽게 설명하면 바이트의 배치 순서라 할 수 있습니다. 서로 다른 엔디안을 사용한다면 문제가 발생하게 됩니다.

> 빅 엔디안
< 리틀 엔디안
@ 로컬 머신 네이티브

엔디안 구분은 <, >로 합니다. @경우 자체 시스템 엔디안을 적용합니다.

with open('test.txt', 'wb') as file:
	str = struct.pack('<Q', ftr)
    	file = f.write(str)

 

피클 패키지

 struct 패키지는 다른 언어에서도 사용 가능하게끔 이식성이 있으나 다소 복잡합니다. 파이썬에서 사용하는 파이썬만의 객체를 직렬화 하는 방법이 피클링입니다.

피클 객체

 바이너리 파일 안에 다음과 같이 피클 객체가 저장되어있는 형태입니다.

 

pickle 메서드

pickle.dump(v, file)

객체를 파일에 쓰는 작업입니다. 인자로 2개의 인자를 받으며 각각 값과 파일입니다. 값 v를 file에 쓰기 합니다. 

pickle.load(file)

 객체를 로드합니다. 얼마나 어떤 타입을 불러와야 하는지는 명시하지 않습니다.

 

pickle 객체

 단순히 두 개의 메서드로 피클을 사용할 수 있습니다. 알아서 검사하기 때문에 필요가 없습니다. 꺼낼 때는 그 객체수만큼 load 하면 됩니다. struct와 달리 calcsize를 사용할 필요가 없는데 파이썬이 알아서 검사를 하기 때문입니다. 다만 파일을 열었을 때 얼마나 객체가 담겨있는지는 알 수가 없습니다. 때문에 더 부를 객체가 없는데도 부르게 된다면 EOF 에러가 발생됩니다. 

import pickle

with open('test.bin', 'wb') as file:
	pickle.dump([1, 2, 3])
    	pickle.dump('ex')
    
with open('test.bin", 'rb') as file:
	pickle.load(file)
    	pickle.load(file)

 

 

pickle 패키지 외에도 shelve 패키지를 사용할 수 있습니다.

 

 

728x90
반응형

댓글