[Python] 파일 압축, 해제(zipfile)하는 방법


Development note/Python  2020. 1. 27. 09:00

안녕하세요. 명월입니다.


이 글은 Python에서 파일 압축, 해제(zipfile)하는 방법에 관한 글입니다.


프로그래밍을 다루면 압축 파일을 상당히 자주 봅니다. 압축의 이점은 크게 데이터의 사이즈를 줄여주는 것도 있고, 그에 비해 일반 파일시스템(IO)처럼 파일 관리가 가능하면서 실제 물리적으로는 하나의 파일로 되어 있기 때문입니다.

Python에서 zip파일을 다루는 모듈은 zipfile입니다.

link - https://docs.python.org/3/library/zipfile.html

# zipfile 모듈
import zipfile;
import os;

# 압축 파일을 생성할 파일의 절대 경로.
with zipfile.ZipFile('d:\\archive.zip', 'w') as myZip:
  # 압축 대상 경로
  des_folder = 'd:\\apache';
  # os 모듈로 해당 경로의 파일을 취득한다.(os.walk는 경로의 하위 폴더까지 취득한다.)
  for folder,subfolders,files in os.walk(des_folder):
    # os.walk로 파일 리스트를 받아 루프를 돌린다.
    for file in files:
      # folder와 files명은 다른 변수로 취득된다. 두 변수값으로 파일 절대 경로를 만든다.
      full_name = os.path.join(folder, file);
      # write은 압축 파일에 파일을 쓰는 것이다. 파라미터는 대상 파일, 저장될 경로로 지정된다.
      # 압축 파일에 저장될 경로는 \기준으로 상대 경로로 작성해야 한다.
      myZip.write(full_name, os.path.relpath(full_name, des_folder));

# 위에서 생성된 압축 파일에 파일을 추가한다.
with zipfile.ZipFile('d:\\archive.zip', 'a') as myZip:
  # work 폴더의 hello.txt 파이를 root의 text.txt 파일로 저장한다.
  myZip.write('d:\\work\hello.txt', 'text.txt');
  # 이건 text1.txt에 string 값으로 파일을 저장한다.
  myZip.writestr('text1.txt', 'hello world string!!');
  # byte 단위로 생성하는 건 없습니다... 아쉽습니다.

먼저 zip 파일 압축을 만드는 예제입니다. ZipFile에서 옵션이 있습니다.

IO랑 비슷한 개념인데 'r','w','a','x'가 있습니다.

w와 x는 파일을 생성하는 옵션인데 w는 해당 파일이 존재하면 삭제하고 생성하고, x는 존재할 경우 FileExistsError 에러를 발생시킵니다.

a의 경우는 존재하는 파일에 추가 파일을 넣거나 수정할 때 사용됩니다.

r의 경우는 zip파일을 읽는 옵션입니다.

결과를 보면 제가 apache 소스를 압축했는데, 추가로 text.txt파일과 text1.txt를 추가했습니다.

# zipfile 모듈
import zipfile;

# 압축 파일을 읽어 드릴 파일의 절대 경로.
with zipfile.ZipFile('d:\\archive.zip', 'r') as myZip:
  # 압축 해제할 때 암호가 걸려있을 경우 설정합니다.(파일 압축 과정에서는 암호를 생성할 수 없습니다.)
  #myZip.setpassword(b'1234');
  # zip파일로 부터 파일 리스트를 받는다.(zip 파일 내의 절대경로입니다.)
  for filename in myZip.namelist():
    # text.txt 파일과 text1.txt를 읽는다,
    if filename == 'text.txt' or filename == 'text1.txt':
      # 파일을 읽어온다.
      with myZip.open(filename) as myfile:
        # 파일을 출력한다. (byte 방식)
        print(myfile.read());
      
      # 위 open과 처리 기능이 같다(byte)
      data = myZip.read(filename);
      # byte to string 변환
      print(data.decode());
      # 압축을 푼다.
      myZip.extract(filename, path='d:\\work\\');

# 전체 파이릉ㄹ 해제한다.     
with zipfile.ZipFile('d:\\archive.zip', 'r') as myZip:
  # 전체 파일을 해제한 경로를 설정한다.
  myZip.extractall(path='d:\\work\\extract\\');

위 예제는 압축 파일을 해제하는 소스입니다. 먼저 zip에서 꼭 해제를 하지 않아도 open이나 read로 파일을 읽어 드릴 수 있습니다.

참고로 위 예제에서는 zipfile.ZipFile을 넣어 압축 파일 넣었는데 stream 타입의 데이터를 넣어서 처리가 가능합니다. 그러면 socket 간에 압축 송수신할 때 굳히 로컬 디스크게 압축을 풀지 않아도 압축 파일의 데이터를 읽을 수 있습니다.

결과는 위 text.txt파일과 text1.txt파일만 읽어 오고, print했습니다. 결과는 「hello world!!」와「hello world string!!」의 결과가 나왔습니다.


python에서는 zipfile모듈에서 따로 압축 파일 내의 파일을 삭제하는 기능이 없네요. 아쉽습니다.


여기까지 Python에서 파일 압축, 해제(zipfile)하는 방법에 관한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.