Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬 내부 객체 직렬화(마샬링) 완벽 가이드

파이썬 marshal 모듈이란?

파이썬 표준 라이브러리의 marshal 모듈은 pickle 모듈과 유사한 객체 직렬화 기능을 제공합니다. 하지만 이 모듈은 일반적인 데이터 영속화(persistence)나 소켓을 통한 파이썬 객체 전송 같은 범용 목적에는 적합하지 않습니다.

marshal 모듈은 주로 파이썬 자체적으로 컴파일된 모듈 파일(.pyc)을 읽고 쓰는 작업을 지원하기 위해 사용됩니다. 특히 주의할 점은 marshal 모듈이 사용하는 데이터 형식이 파이썬 버전 간 호환되지 않는다는 것입니다. 하위 버전 사이에서도 호환이 보장되지 않기 때문에, 특정 버전으로 컴파일된 파이썬 스크립트(.pyc 파일)는 다른 버전에서는 대부분 실행되지 않습니다. 이러한 이유로 marshal 모듈은 파이썬의 내부 객체 직렬화 용도로 한정되어 사용됩니다.

marshal 모듈의 주요 함수

pickle 모듈과 마찬가지로 marshal 모듈도 파일 입출력을 위한 load(), dump() 함수와 문자열(바이트) 표현을 다루는 loads(), dumps() 함수를 제공합니다.

dumps() – 객체를 바이트로 변환

dumps() 함수는 파이썬 객체를 마샬링하여 바이트(bytes)류 객체로 반환합니다. 단, 표준 데이터 타입의 객체만 마샬링할 수 있으며, 지원되지 않는 타입을 전달하면 ValueError 예외가 발생합니다.

loads() – 바이트를 객체로 복원

loads() 함수는 바이트류 객체를 원래의 파이썬 객체로 되돌립니다. 변환 결과가 유효한 파이썬 객체가 아니면 ValueError 또는 TypeError 예외가 발생할 수 있습니다.

다음 예제는 딕셔너리 객체를 dumps()로 마샬링한 뒤, loads()로 다시 딕셔너리로 복원하는 과정을 보여줍니다.

import marshal
person = {"name":"xyz", "age":22, "marks":[45,56,78]}
data = marshal.dumps(person)
obj = marshal.loads(data)
print (obj)

dump() – 파일에 객체 저장

dump() 함수는 지원되는 파이썬 객체의 바이트 표현을 파일에 기록합니다. 이때 대상 파일은 반드시 쓰기 권한이 있는 바이너리 파일이어야 합니다.

load() – 파일에서 객체 읽기

load() 함수는 바이너리 파일에서 바이트 데이터를 읽어 파이썬 객체로 변환합니다.

.pyc 파일 처리 실습

앞서 언급했듯이 marshal 모듈은 .pyc 파일을 처리하는 데 사용됩니다. 다음 예제는 미리 컴파일된 파이썬 모듈을 저장하는 데 쓰이는 코드 객체(code object)dump()load() 함수로 다루는 방법을 보여줍니다.

먼저 내장 함수 compile()을 사용해 파이썬 코드가 담긴 소스 문자열로부터 코드 객체를 생성합니다.

compile(source, file, mode)
  • file 매개변수: 코드를 읽어온 파일 이름입니다. 파일에서 읽은 것이 아니라면 임의의 문자열을 지정해도 됩니다.
  • mode 매개변수: 소스가 여러 문(statement)의 나열이면 'exec', 단일 표현식이면 'eval', 단일 대화형 문장이면 'single'을 지정합니다.

컴파일된 코드 객체는 dump() 함수를 통해 .pyc 파일에 저장됩니다.

import marshal
script = """
a = 10
b = 20
print ('addition = ',a+b)
"""
code = compile(script, "script", "exec")
f = open("a.pyc","wb")
marshal.dump(code, f)
f.close()

.pyc 파일에서 객체를 역직렬화하려면 load() 함수를 사용합니다. 이 함수는 코드 객체를 반환하므로, 또 다른 내장 함수인 exec()를 이용해 곧바로 실행할 수 있습니다.

import marshal
f = open("a.pyc","rb")
data = marshal.load(f)
exec (data)

실행 결과는 소스 문자열에 포함된 코드 블록의 출력과 동일합니다.

addition = 30