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

파이썬 zipfile 모듈로 파일 압축하는 방법 완벽 가이드

문제 상황

파이썬으로 여러 개의 파일을 하나의 ZIP 아카이브로 압축하고 싶습니다.

개요

ZIP 파일은 여러 개의 파일 내용을 압축하여 하나의 아카이브에 담을 수 있는 형식입니다. 파일을 압축하면 디스크 용량을 절약할 수 있으며, 인터넷을 통해 전송하거나 Control-M AFT, Connect:Direct, scp 등을 이용해 시스템 간에 파일을 주고받을 때 특히 유용합니다.

파이썬 프로그램은 표준 라이브러리인 zipfile 모듈의 함수들을 사용하여 ZIP 파일을 손쉽게 생성할 수 있습니다.

구현 방법

1단계: 필요한 패키지 준비

이 예제에서는 zipfile, io, pandas 패키지를 사용합니다. 시스템에 패키지가 없다면 pip로 설치하세요. 설치 여부가 확실하지 않다면 pip freeze 명령어로 확인할 수 있습니다.

2단계: 데이터를 파일로 저장하는 함수 작성

먼저 문자열 데이터를 CSV 파일로 저장하는 함수를 작성합니다. 아래의 write_data_to_files 함수는 데이터와 파일명을 입력받아 현재 디렉터리에 해당 이름의 파일을 생성합니다.

# 함수 : write_data_to_files
def write_data_to_files(inp_data, file_name):
    """
    function : 전달받은 데이터로 csv 파일 생성
    args : inp_data : 대상 파일에 기록할 데이터
           file_name : 데이터를 저장할 대상 파일명
    return : none
    assumption : 생성될 파일과 이 코드가 같은 디렉터리에 있음.
    """
    print(f" *** Writing the data to - {file_name}")
    throwaway_storage = io.StringIO(inp_data)
    with open(file_name, 'w') as f:
        for line in throwaway_storage:
            f.write(line)

3단계: 파일을 ZIP으로 압축하는 함수 작성

이제 위 단계에서 생성한 파일들을 ZIP으로 묶는 file_compress 함수를 작성합니다. 이 함수는 파일명 리스트를 입력받아 각 파일을 순회하며 하나의 ZIP 파일로 압축합니다. 각 단계에 대한 자세한 설명은 코드의 주석에 포함되어 있습니다.

직접 압축된 ZIP 파일을 만들려면 ZipFile 객체를 쓰기(write) 모드로 열어야 합니다. 즉, 두 번째 인자로 'w'를 전달하면 됩니다.

  • write() 메서드의 첫 번째 인자: ZIP 파일에 추가할 파일명(경로) 문자열입니다. 경로를 전달하면 파이썬은 해당 경로의 파일을 압축하여 ZIP 파일에 추가합니다.

  • 두 번째 인자: 압축 방식(compression type) 매개변수로, 컴퓨터가 어떤 알고리즘으로 파일을 압축할지 지정합니다.

# 함수 : file_compress
def file_compress(inp_file_names, out_zip_file):
    """
    function : file_compress
    args : inp_file_names : zip으로 묶을 파일명 리스트
           out_zip_file : 출력 zip 파일명
    return : none
    assumption : 입력 파일 경로와 이 코드가 같은 디렉터리에 있음.
    """
    # 압축 시에는 ZIP_DEFLATED 모드 선택
    # 또는 zipfile.ZIP_STORED를 사용하면 압축 없이 저장만 함
    compression = zipfile.ZIP_DEFLATED
    print(f" *** Input File name passed for zipping - {inp_file_names}")

    # zip 파일 생성 - 첫 번째 매개변수: 경로/파일명, 두 번째: 모드
    print(f' *** out_zip_file is - {out_zip_file}')
    zf = zipfile.ZipFile(out_zip_file, mode="w")

    try:
        for file_to_write in inp_file_names:
            # zip 파일에 파일 추가
            # 첫 번째 매개변수: 압축할 파일, 두 번째: zip 내부의 파일명
            print(f' *** Processing file {file_to_write}')
            zf.write(file_to_write, file_to_write, compress_type=compression)

    except FileNotFoundError as e:
        print(f' *** Exception occurred during zip process - {e}')
    finally:
        # 파일을 반드시 닫아주세요!
        zf.close()

4단계: 함수 호출 및 실행

이제 함수들을 호출하여 두 개의 CSV 파일을 생성한 후 하나의 ZIP 파일로 압축해 보겠습니다. 그랜드슬램 타이틀을 2개 이상 획득한 테니스 선수 데이터를 temporary_file1_for_zip.csv에, 1개 이하로 획득한 선수 데이터를 temporary_file2_for_zip.csv에 저장한 뒤, 두 파일을 모두 temporary.zip으로 압축합니다.

import zipfile
import io
import pandas as pd

file_name1 = "temporary_file1_for_zip.csv"
file_name2 = "temporary_file2_for_zip.csv"
file_name_list = [file_name1, file_name2]
zip_file_name = "temporary.zip"

# 파일 1에 들어갈 데이터
file_data_1 = """
player,titles
Federer,20
Nadal,20
Djokovic,17
Murray,3
"""

# 파일 2에 들어갈 데이터
file_data_2 = """
player,titles
Thiem,1
Zverev,0
Medvedev,0
Rublev,0
"""

# file_data를 file_name에 기록
write_data_to_files(file_data_1, file_name1)
write_data_to_files(file_data_2, file_name2)

# file_name을 zip_file_name으로 압축
file_compress(file_name_list, zip_file_name)

전체 코드 통합

위에서 설명한 모든 단계를 하나의 완전한 스크립트로 정리하면 다음과 같습니다.

import zipfile
import io
import pandas as pd

# 함수 : write_data_to_files
def write_data_to_files(inp_data, file_name):
    """
    function : 전달받은 데이터로 csv 파일 생성
    args : inp_data : 대상 파일에 기록할 데이터
           file_name : 데이터를 저장할 대상 파일명
    return : none
    assumption : 생성될 파일과 이 코드가 같은 디렉터리에 있음.
    """
    print(f" *** Writing the data to - {file_name}")
    throwaway_storage = io.StringIO(inp_data)
    with open(file_name, 'w') as f:
        for line in throwaway_storage:
            f.write(line)

# 함수 : file_compress
def file_compress(inp_file_names, out_zip_file):
    """
    function : file_compress
    args : inp_file_names : zip으로 묶을 파일명 리스트
           out_zip_file : 출력 zip 파일명
    return : none
    assumption : 입력 파일 경로와 이 코드가 같은 디렉터리에 있음.
    """
    compression = zipfile.ZIP_DEFLATED
    print(f" *** Input File name passed for zipping - {inp_file_names}")

    print(f' *** out_zip_file is - {out_zip_file}')
    zf = zipfile.ZipFile(out_zip_file, mode="w")

    try:
        for file_to_write in inp_file_names:
            print(f' *** Processing file {file_to_write}')
            zf.write(file_to_write, file_to_write, compress_type=compression)

    except FileNotFoundError as e:
        print(f' *** Exception occurred during zip process - {e}')
    finally:
        zf.close()

# __main__ 프로그램
if __name__ == '__main__':
    # 파일명과 데이터 정의
    file_name1 = "temporary_file1_for_zip.csv"
    file_name2 = "temporary_file2_for_zip.csv"

    file_name_list = [file_name1, file_name2]
    zip_file_name = "temporary.zip"

    file_data_1 = """
player,titles
Federer,20
Nadal,20
Djokovic,17
Murray,3
"""

    file_data_2 = """
player,titles
Thiem,1
Zverev,0
Medvedev,0
Rublev,0
"""
    # file_data를 file_name에 기록
    write_data_to_files(file_data_1, file_name1)
    write_data_to_files(file_data_2, file_name2)

    # file_name을 zip_file_name으로 압축
    file_compress(file_name_list, zip_file_name)
*** Writing the data to - temporary_file1_for_zip.csv
*** Writing the data to - temporary_file2_for_zip.csv
*** Input File name passed for zipping - ['temporary_file1_for_zip.csv', 'temporary_file2_for_zip.csv']
*** out_zip_file is - temporary.zip
*** Processing file temporary_file1_for_zip.csv
*** Processing file temporary_file2_for_zip.csv

실행 결과

위 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다.

  • 현재 디렉터리에 temporary_file1_for_zip.csv 파일이 생성됩니다.

  • 현재 디렉터리에 temporary_file2_for_zip.csv 파일이 생성됩니다.

  • 현재 디렉터리에 temporary.zip 파일이 생성됩니다.

마무리

파이썬의 zipfile 모듈을 활용하면 별도의 외부 도구 없이도 순수 파이썬 코드만으로 파일 압축을 자동화할 수 있습니다. 로그 파일 백업, 대용량 데이터 전송 전 사전 압축, 배치 작업 결과물 패키징 등 다양한 실무 시나리오에 응용해 보세요. 참고로 ZIP_DEFLATED 대신 zipfile.ZIP_STORED를 사용하면 압축 없이 파일을 단순히 묶기만 할 수도 있습니다.