marshal — Python 객체 내부 직렬화
marshal — Python 객체 내부 직렬화
marshal 모듈은 Python 값을 이진 형식으로 읽고 쓸 수 있는 함수를 포함해요. 형식은 Python에 특화돼 있지만 머신 아키텍처와는 독립적이에요(예컨대 PC에서 파일에 Python 값을 쓰고 그 파일을 Mac으로 옮겨 다시 읽을 수 있어요). 형식의 세부 사항은 의도적으로 문서화하지 않았어요. Python 버전 사이에 바뀔 수 있기 때문이죠(드물게 바뀌지만요).
이것은 일반적인 "영속화(persistence)" 모듈이 아니에요. 일반적 영속화와 RPC 호출을 통한 Python 객체 전송은 pickle과 shelve 모듈을 참고하세요. marshal 모듈은 주로 .pyc 파일인 Python 모듈의 "의사 컴파일된(pseudo-compiled)" 코드를 읽고 쓰는 걸 지원하기 위해 존재해요. 그래서 Python 관리자들은 필요할 경우 marshal 형식을 하위 호환이 안 되는 방식으로 수정할 권리를 보유해요.
코드 객체의 형식은 형식 버전이 같더라도 Python 버전 사이에 호환되지 않아요. 잘못된 Python 버전에서 코드 객체를 역직렬화하면 정의되지 않은 동작이 돼요. Python 객체를 직렬화·역직렬화한다면 대신 pickle 모듈을 쓰세요. 성능은 비슷하고 버전 독립성이 보장되며, pickle은 marshal보다 훨씬 넓은 객체 범위를 지원해요.
경고:
marshal모듈은 오류가 있거나 악의적으로 만들어진 데이터에 대해 안전하도록 설계되지 않았어요. 신뢰할 수 없거나 인증되지 않은 출처의 데이터를 절대 unmarshal하지 마세요.
파일을 읽고 쓰는 함수와 bytes-like 객체를 다루는 함수가 둘 다 있어요. 모든 Python 객체 타입이 지원되지는 않아요. 일반적으로 값이 특정 Python 실행과 무관한 객체만 이 모듈로 쓰고 읽을 수 있어요. 지원되는 타입은 다음과 같아요:
- 숫자 타입:
int,bool,float,complex. - 문자열(
str)과bytes. bytearray같은 bytes-like 객체는bytes로 marshall돼요.- 컨테이너:
tuple,list,set,frozenset, 그리고 (버전 5부터)slice.
이들은 그 안에 담긴 값이 지원되는 경우에만 지원된다는 점을 이해해야 해요. 재귀 컨테이너는 버전 3부터 지원돼요. 싱글턴 None, Ellipsis, StopIteration도 지원돼요. allow_code가 참이면 코드 객체도 지원돼요(버전 의존성에 관한 앞의 참고 참고).
버전 3.4에서 변경: 재귀 리스트·집합·딕셔너리를 marshall하는 형식 버전 3 추가. 짧은 문자열의 효율적 표현을 지원하는 형식 버전 4 추가. 버전 3.14에서 변경: slice를 marshall할 수 있는 형식 버전 5 추가.
출처: Python 표준 라이브러리
본문
모듈은 다음 함수들을 정의해요.
marshal.dump(value, file, version=version, /, *, allow_code=True)
열린 파일에 value를 써요. value는 지원되는 타입이어야 해요. 파일은 쓰기 가능한 바이너리 파일이어야 해요.
값이(또는 그 안에 든 객체가) 지원되지 않는 타입을 가지면 ValueError 예외가 나요. 하지만 쓰레기 데이터도 파일에 쓰여져서, 그 객체는 load()로 제대로 다시 읽히지 않아요. 코드 객체는 allow_code가 참일 때만 지원돼요.
version 인자는 dump가 사용할 데이터 형식을 나타내요(아래 참고). auditing 이벤트 marshal.dumps를 인자 value, version으로 일으켜요.
버전 3.13에서 변경: allow_code 매개변수 추가.
marshal.load(file, /, *, allow_code=True)
열린 파일에서 값을 하나 읽어 돌려줘요. 유효한 값을 읽지 못하면(예: 데이터가 다른 Python 버전의 호환되지 않는 marshal 형식일 때) EOFError, ValueError 또는 TypeError를 일으켜요. 코드 객체는 allow_code가 참일 때만 지원돼요. 파일은 읽기 가능한 바이너리 파일이어야 해요. 인자 없이 auditing 이벤트 marshal.load를 일으켜요.
참고:
dump()로 지원되지 않는 타입을 담은 객체를 marshall했다면,load()는 unmarshall할 수 없는 타입을None으로 대체해요.
버전 3.10에서 변경: 이 호출은 이전에 각 코드 객체에 대해 code.__new__ audit 이벤트를 일으켰어요. 이제 전체 load 작업에 대해 단일 marshal.load 이벤트를 일으켜요.
버전 3.13에서 변경: allow_code 매개변수 추가.
marshal.dumps(value, version=version, /, *, allow_code=True)
dump(value, file)가 파일에 쓸 bytes 객체를 돌려줘요. value는 지원되는 타입이어야 해요. value가(또는 그 안에 든 객체가) 지원되지 않는 타입을 가지면 ValueError 예외를 일으켜요. 코드 객체는 allow_code가 참일 때만 지원돼요. version 인자는 dumps가 사용할 데이터 형식을 나타내요(아래 참고). auditing 이벤트 marshal.dumps를 인자 value, version으로 일으켜요.
버전 3.13에서 변경: allow_code 매개변수 추가.
marshal.loads(bytes, /, *, allow_code=True)
bytes-like 객체를 값으로 변환해요. 유효한 값을 찾지 못하면 EOFError, ValueError 또는 TypeError를 일으켜요. 코드 객체는 allow_code가 참일 때만 지원돼요. 입력의 여분 bytes는 무시돼요. 인자 bytes로 auditing 이벤트 marshal.loads를 일으켜요.
버전 3.10에서 변경: 이 호출은 이전에 각 코드 객체에 대해 code.__new__ audit 이벤트를 일으켰어요. 이제 전체 load 작업에 대해 단일 marshal.loads 이벤트를 일으켜요.
버전 3.13에서 변경: allow_code 매개변수 추가.
marshal.version
모듈이 사용하는 형식을 나타내요. 버전 0은 역사적인 첫 버전이고, 이후 버전이 새 기능을 추가해요. 일반적으로 새 버전이 도입되면 기본값이 돼요.
| 버전 | 사용 가능부터 | 새 기능 |
|---|---|---|
| 1 | Python 2.4 | Interned 문자열 공유 |
| 2 | Python 2.5 | Float의 이진 표현 |
| 3 | Python 3.4 | 객체 인스턴싱과 재귀 지원 |
| 4 | Python 3.4 | 짧은 문자열의 효율적 표현 |
| 5 | Python 3.14 | slice 객체 지원 |
더 알아보기
pickle— Python 객체 영속화의 권장 방식.marshal보다 넓은 타입을 지원하고 버전 독립성을 보장해요.shelve— Python 객체 영속화.dbm— Unix "데이터베이스" 인터페이스.