zipapp — 실행 가능한 Python zip 아카이브 관리

zipapp — 실행 가능한 Python zip 아카이브 관리

이 모듈은 Python 인터프리터가 직접 실행할 수 있는 Python 코드가 담긴 zip 파일 생성을 관리하는 도구를 제공해요. 모듈은 명령줄 인터페이스(Command-Line Interface)와 Python API를 모두 제공해요. 버전 3.5에서 추가되었어요.

출처: Python documentation

본문

기본 예제 (Basic Example)

다음 예제는 명령줄 인터페이스를 사용해 Python 코드가 담긴 디렉터리에서 실행 가능한 아카이브를 만드는 방법을 보여줘요. 실행하면 아카이브의 myapp 모듈에서 main 함수를 실행해요.

$ python -m zipapp myapp -m "myapp:main"
$ python myapp.pyz
<output from myapp>

명령줄 인터페이스 (Command-Line Interface)

$ python -m zipapp source [options]

source가 디렉터리이면 그 내용에서 아카이브를 만들어요. source가 파일이면 아카이브여야 하며, 대상 아카이브로 복사되거나(--info 옵션이 지정되면 shebang 줄의 내용이 표시됨) 돼요.

옵션:

  • -o <output>, --output=<output> — 이름이 output인 파일에 출력 작성. 지정하지 않으면 출력 파일 이름은 입력 소스와 같고 .pyz 확장자가 추가돼요.
  • -p <interpreter>, --python=<interpreter>interpreter를 실행 명령으로 지정하는 #! 줄을 아카이브에 추가. POSIX에서는 아카이브를 실행 가능하게 만들어요. 기본은 #! 줄을 쓰지 않고 파일을 실행 가능하게 하지 않는 것.
  • -m <mainfn>, --main=<mainfn>mainfn을 실행하는 __main__.py 파일을 아카이브에 써요. mainfn 인자는 "pkg.mod:fn" 형태여야 해요. --main은 아카이브를 복사할 때는 지정할 수 없어요.
  • -c, --compress — deflate 방식으로 파일을 압축해 출력 파일 크기를 줄여요. 기본적으로 파일은 압축 없이 저장돼요.
  • --info — 진단 목적으로 아카이브에 포함된 인터프리터를 표시. 이 경우 다른 옵션은 무시되고 SOURCE는 디렉터리가 아닌 아카이브여야 해요.
  • -h, --help — 짧은 사용법 메시지 출력 후 종료

Python API

zipapp.create_archive(source, target=None, interpreter=None, main=None, filter=None, compressed=False)

source에서 애플리케이션 아카이브를 만들어요. source는 디렉터리 이름, 기존 애플리케이션 아카이브 파일 이름, 또는 바이트 모드로 읽기 위해 열린 파일 객체일 수 있어요. target 인자는 결과 아카이브가 쓰일 위치를 결정해요. interpreter 인자는 아카이브가 실행될 Python 인터프리터의 이름을 지정하며, 아카이브 시작 부분에 "shebang" 줄로 기록돼요. main 인자는 아카이브의 메인 프로그램으로 사용될 호출 가능 객체의 이름을 지정하며, source가 디렉터리이고 __main__.py 파일이 이미 포함되어 있지 않을 때만 지정할 수 있어요. filter 인자는 추가되는 파일 경로를 나타내는 Path 객체를 받는 콜백 함수를 지정해요. compressed 인자는 파일이 압축되는지 여부를 결정해요.

zipapp.get_interpreter(archive)

아카이브 시작 부분의 #! 줄에 지정된 인터프리터를 반환해요. #! 줄이 없으면 None을 반환해요.

예제 (Examples)

# 디렉터리를 아카이브로 묶고 실행
$ python -m zipapp myapp
$ python myapp.pyz

create_archive() 함수로도 할 수 있어요:

>>> import zipapp
>>> zipapp.create_archive('myapp', 'myapp.pyz')

POSIX에서 직접 실행 가능하게 하려면 사용할 인터프리터를 지정해요:

$ python -m zipapp myapp -p "/usr/bin/env python"
$ ./myapp.pyz

인터프리터 지정 (Specifying the Interpreter)

/usr/bin/env python 또는 python3 같은 방식을 사용할 때는 사용자가 기본으로 Python 2 또는 Python 3을 가질 수 있다는 점과 코드가 두 버전 모두에서 작동하는지 고려해야 해요. 일반적으로 코드가 Python 2용인지 3용인지에 따라 /usr/bin/env python2 또는 /usr/bin/env python3을 사용해야 해요.

zipapp으로 독립 실행 애플리케이션 생성 (Creating Standalone Applications)

zipapp 모듈을 사용하면 시스템에 적절한 버전의 Python만 설치되어 있으면 되는 최종 사용자에게 배포할 수 있는 자체 포함(self-contained) Python 프로그램을 만들 수 있어요. 핵심은 애플리케이션 코드와 함께 모든 종속성을 아카이브에 번들하는 것이에요.

단계:

  1. __main__.py 파일과 지원 코드가 있는 myapp 디렉터리에 애플리케이션 생성
  2. pip로 모든 종속성을 myapp 디렉터리에 설치: $ python -m pip install -r requirements.txt --target myapp
  3. 애플리케이션 패키징: $ python -m zipapp -p "interpreter" myapp

주의사항 (Caveats)

애플리케이션이 C 확장을 포함하는 패키지에 의존하면 그 패키지는 zip 파일에서 실행할 수 없어요(실행 코드가 OS 로더가 로드할 수 있도록 파일 시스템에 있어야 하는 OS 제한 때문). 이 경우 해당 종속성을 zipfile에서 제외하고, 사용자가 설치하도록 요구하거나, 압축 해제된 모듈을 포함하는 디렉터리를 sys.path에 추가하는 코드를 __main__.py에 넣어야 해요.

Python Zip 애플리케이션 아카이브 형식 (The Python Zip Application Archive Format)

Python은 2.6부터 __main__.py 파일을 포함하는 zip 파일을 실행할 수 있었어요. 애플리케이션 아카이브는 실행되려면 단순히 __main__.py 파일을 포함하는 표준 zip 파일이면 돼요. 공식적으로 Python zip 애플리케이션 형식은 다음과 같아요:

  • 선택적 shebang 줄: b'#!' 문자와 인터프리터 이름, 개행(b'\n') 문자 포함
  • zipfile 모듈이 생성하는 표준 zipfile 데이터. zipfile 내용은 __main__.py 파일을 포함해야 해요(반드시 zipfile의 "루트"에 있어야 하며 하위 디렉터리에 있을 수 없음)

이 모듈의 도구를 사용해 애플리케이션 아카이브를 만들 필요는 없어요 — 모듈은 편의일 뿐이며, 위 형식의 아카이브는 어떤 수단으로 만들어도 Python이 받아들여요.

더 알아보기 (Learn more)