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

Python lzma 모듈로 LZMA 알고리즘 압축 완벽 가이드

LZMA 알고리즘 개요

LZMA(Lempel–Ziv–Markov chain Algorithm)는 사전 기반 압축 방식을 활용해 무손실 데이터 압축을 수행하는 알고리즘으로, 다른 압축 알고리즘에 비해 월등히 높은 압축률을 자랑합니다. Python의 lzma 모듈은 이 알고리즘으로 데이터를 압축하고 해제할 수 있는 다양한 클래스와 편의 함수들을 제공합니다.

이 모듈은 bz2 모듈과 기능이 매우 유사하지만 한 가지 중요한 차이점이 있습니다. BZ2File 클래스와 달리 LZMAFile 클래스는 스레드 안전(thread-safe)하지 않으므로, 멀티스레드 환경에서 사용할 때는 주의가 필요합니다.

lzma 모듈에서 압축 파일 객체를 여는 가장 간단한 방법은 open() 함수를 사용하는 것입니다.

open() – 압축 파일 열기

이 함수는 LZMA로 압축된 파일을 열고 파일 객체를 반환합니다. 파일 이름과 모드(mode)라는 두 가지 주요 인자가 필요하며, mode의 기본값은 "rb"입니다. 지정할 수 있는 모드는 다음과 같습니다.

바이너리 모드 - "r", "rb", "w", "wb", "x", "xb", "a", "ab"
텍스트 모드 - "rt", "wt", "xt", "at"

compress() – 데이터 압축

이 함수는 전달된 데이터를 LZMA 알고리즘으로 압축하여 바이트(bytes) 객체를 반환합니다. 선택적으로 컨테이너 형식을 결정하는 format 인자를 지정할 수 있으며, 가능한 값은 FORMAT_XZ(기본값)와 FORMAT_ALONE입니다.

decompress() – 데이터 해제

이 함수는 압축된 데이터를 해제하여 원본 바이트 객체를 반환합니다.

다음 예제는 위 함수들을 활용해 LZMA 압축 데이터를 파일에 쓰는 방법을 보여줍니다.

>>> import lzma
>>> data = b"Welcome to TutorialsPoint"
>>> f = lzma.open("test.xz", "wb")
>>> f.write(data)
>>> f.close()

코드를 실행하면 현재 작업 디렉터리에 'test.xz' 파일이 생성됩니다. 이 파일에서 원본 데이터를 읽어오려면 다음 코드를 사용합니다.

>>> import lzma
>>> f = lzma.open("test.xz", "rb")
>>> data = f.read()
>>> data
b'Welcome to TutorialsPoint'

객체 지향 API – LZMAFile 클래스

lzma 모듈의 객체 지향 API를 사용해 압축을 수행하려면 LZMAFile 클래스를 활용하면 됩니다.

LZMAFile()

LZMAFile 클래스의 생성자입니다. 파일과 모드를 반드시 지정해야 하며, 'w' 또는 'wb' 모드로 생성한 객체에는 write() 메서드를 사용할 수 있습니다.

write()

전달된 데이터를 압축하여 내부 파일에 기록합니다.

>>> data = b'Welcome to TutorialsPoint'
>>> obj = lzma.LZMAFile("test.xz", mode="wb")
>>> obj.write(data)
>>> obj.close()

'rb' 모드로 생성한 LZMAFile 객체의 read() 메서드를 호출하면 압축 파일을 읽어 원본 데이터를 얻을 수 있습니다.

read()

압축 파일에서 데이터를 읽어 해제된(원본) 데이터를 반환합니다.

>>> obj = lzma.LZMAFile("test.xz", mode="rb")
>>> data = obj.read()
>>> data
b'Welcome to TutorialsPoint'

이미 열려 있는 파일에 압축 데이터 쓰기

LZMA 알고리즘은 이미 열려 있는 파일 객체에도 압축 데이터를 기록할 수 있습니다. 다음 예제에서는 내장 open() 함수로 'test.txt'를 'wb' 모드로 연 뒤 일반 텍스트를 먼저 기록하고, 이후 같은 파일에 압축 데이터를 추가로 기록합니다.

>>> f = open("test.txt", "wb")
>>> f.write(b"Hello world")
>>> fp = lzma.open(f, "wb")
>>> fp.write(b"Welcome to Python")
>>> f.write(b"Thank you")
>>> f.close()
>>> fp.flush()
>>> fp.close()

실행 결과 현재 디렉터리에 생성된 'test.txt'에는 아래처럼 압축 데이터와 일반 텍스트가 섞여 저장됩니다.

Hello worldý7zXZ æÖ´F!t/å£Thank you

증분 압축기와 해제기

bz2 모듈과 마찬가지로 lzma 모듈에도 증분(incremental) 방식의 압축기와 해제기 클래스가 마련되어 있습니다.

LZMACompressor()

증분 압축기 객체를 반환하는 생성자입니다. 여러 데이터 조각(chunk)을 개별적으로 압축한 뒤, 그 결과를 이어 붙여 하나의 파일에 기록할 수 있습니다.

compress()

전달된 데이터를 압축하여 바이트 객체를 반환합니다.

flush()

버퍼를 비우고 남아 있는 데이터를 바이트 객체로 반환합니다.

다음 예제는 증분 압축기를 사용해 리스트 객체를 압축하는 과정을 보여줍니다.

>>> data = [b'Hello World', b'How are you?', b'welcome to Python']
>>> obj = lzma.LZMACompressor()
>>> bindata = []
>>> for i in data:
... bindata.append(obj.compress(i))
>>> bindata.append(obj.flush())
>>> bindata
[b'\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3', b'', b'', b"\x01\x00'Hello WorldHow are you?welcome to Python\x00\xf5\xc6\xc1d|\xf3\x8ey\x00\x01@(\xd4RJ\xe5\x1f\xb6\xf3}\x01\x00\x00\x00\x00\x04YZ"]

위 코드는 원본 리스트의 각 항목을 압축한 바이트 표현들로 bindata 리스트를 구성합니다. LZMADecompressor 객체로 원본 데이터를 복원하려면 다음과 같이 작성합니다.

>>> obj = lzma.LZMADecompressor()
>>> binstr = b''.join(bindata)
>>> obj.decompress(binstr)
b'Hello WorldHow are you?welcome to Python'

마무리

이 글에서는 Python lzma 모듈의 주요 클래스와 함수들을 예제와 함께 살펴보았습니다. open() 함수를 이용한 간편한 파일 입출력부터 LZMAFile, LZMACompressor, LZMADecompressor를 활용한 세밀한 압축 제어까지, 상황에 맞는 방식을 선택해 효율적인 데이터 압축을 구현해 보시기 바랍니다.