ZipFile 모듈 사용 - 압축파일 처리

zipfile 모듈은 zip, bzip, lzma 형식의 압축 파일을 처리할 수 있다. 하지만 각 형식을 처리하기 위한 모듈이 설치되어 있어야 한다. 그 이외의 압축 형식은 NotImplementedError 예외가 발생한다. zipfile 모듈의 자세한 설명은 아래 문서를 참고 하도록 한다.

 

zipfile — Work with ZIP archives — Python 3.9.1 documentation

zipfile — Work with ZIP archives Source code: Lib/zipfile.py The ZIP file format is a common archive and compression standard. This module provides tools to create, read, write, append, and list a ZIP file. Any advanced use of this module will require an

docs.python.org

아래 코드는 zipfile을 생성하는 간단한 예제이며, compression을 설정하지 않으면 tar처럼 압축 없이 여러 개의 파일을 하나로 합치기만 한다.

import os
import zipfile

def make_zipfile(zipfile_dir):
    zipfile_name = zipfile_dir + '.zip'

    if os.path.exists(zipfile_name):
        os.remove(zipfile_name)

    with zipfile.ZipFile(zipfile_name, 'w', compression=zipfile.ZIP_DEFLATED) as f:
        for base, dirs, files in os.walk(zipfile_dir):
            for d_name in dirs:
                dir_name = os.path.join(base, d_name)
                f.write(dir_name)

            for file in files:
                file_name = os.path.join(base, file)
                f.write(file_name)

    return zipfile_name

위 코드에서 zipfile_dir 디렉토리 경로가 relative path가 아닌 absolute path로 설정되어 있다면 압축 파일의 디렉토리 경로는 압축 파일의 전체 디렉토리 경로를 포함한 상태로 압축되는 것을 명심하도록 한다. 그래서 압축 파일이 전체 디렉토리를 경로를 포함하지 않게 하기 위해 위의 코드를 아래와 같이 변경할 수 있다.

zipfile_dir 경로가 absolute path로 전달되면, f.write()에서 전체 디렉토리 경로가 포함된 상태로 압축파일을 생성하기 때문에, f.write() 메소드에서 arc_name 파라미터로 archive file path를 아래와 같이 다시 설정할 수 있다.

-                f.write(dir_name)
+                f.write(file_name, file_name[len(parent_dir):])

그리고, f.infolist() 메소드를 사용하여 압축된 파일의 정보를 아래와 같이 추출할 수 있다. f.infolist() 메소드는 압축된 파일을 interator로 반환한다.

def display_zipfile(zipfile_name):
    with zipfile.ZipFile(zipfile_name, 'r') as f:
        for zip_file in f.infolist():
            print('----------------------------------------------------')
            if zip_file.is_dir():
                print('dir name   :', zip_file.filename)
            else:
                print('file name  :', zip_file.filename)
                print('file size  :', zip_file.file_size)
                print('comp type  :', zip_file.compress_type)
                print('comp size  :', zip_file.compress_size)

마지막으로, 아래 코드와 같이 간단하게 extactall() 함수를 이용하여 압축된 파일을 풀 수 있다.

if __name__ == '__main__':
    zipfile_name = make_zipfile('data')
    display_zipfile(zipfile_name)
    zipfile.ZipFile(zipfile_name).extractall()

extract(file_name)은 특정 파일만 선택적으로 풀 수 있으며, shutil 모듈을 사용하면 좀 더 유연하게 사용할 수 있는 것 같은데, 이것은 추후 살펴보도록 하자.