"zipapp" --- 실행 가능한 파이썬 zip 아카이브 관리
*************************************************

Added in version 3.5.

**소스 코드:** Lib/zipapp.py

======================================================================

이 모듈은 파이썬 인터프리터가 직접 실행할 수 있는 파이썬 코드를 포함하
는 zip 파일 생성을 관리하는 도구를 제공합니다. 이 모듈은 명령 줄 인터
페이스와 파이썬 API를 모두 제공합니다.


기본 예
=======

다음 예제는 명령 줄 인터페이스를 사용하여 파이썬 코드가 포함된 디렉터
리에서 실행 가능 아카이브를 만드는 방법을 보여줍니다. 실행하면, 아카이
브가 아카이브의 모듈 "myapp"에서 "main" 함수를 실행합니다.

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


명령 줄 인터페이스
==================

명령 줄에서 프로그램으로 호출될 때, 다음 형식이 사용됩니다:

   $ python -m zipapp source [options]

*source*가 디렉터리면, *source*의 내용으로부터 아카이브를 만듭니다.
*source*가 파일이면, 아카이브여야 하며, 대상 아카이브로 복사됩니다 (또
는 --info 옵션이 지정되면 셔뱅(shebang) 줄의 내용이 표시됩니다).

다음과 같은 옵션이 이해됩니다:

-o <output>, --output=<output>

   출력을 *output*이라는 이름의 파일에 씁니다. 이 옵션을 지정하지 않으
   면, 출력 파일명은 입력 *source*와 같고, 확장자 ".pyz"가 추가됩니다.
   명시적인 파일명이 제공되면, 그대로 사용됩니다 (그래서 필요하면
   ".pyz" 확장자를 포함해야 합니다).

   *source*가 아카이브이면 반드시 출력 파일명을 지정해야 합니다 (그리
   고 이 경우, *output*은 *source*와 달라야 합니다).

-p <interpreter>, --python=<interpreter>

   실행할 명령으로 *interpreter*를 지정하여 "#!" 줄을 아카이브에 추가
   합니다. 또한, POSIX에서, 아카이브를 실행 파일로 만듭니다. 기본값은
   "#!" 줄을 쓰지 않고, 파일을 실행 파일로 만들지 않는 것입니다.

-m <mainfn>, --main=<mainfn>

   아카이브에 *mainfn*을 실행하는 "__main__.py" 파일을 씁니다.
   *mainfn* 인자는 "pkg.mod:fn" 형식이어야 합니다. 여기서 "pkg.mod"는
   아카이브의 패키지/모듈이며, "fn"은 주어진 모듈에 있는 콜러블입니다.
   "__main__.py" 파일은 그 콜러블을 실행합니다.

   아카이브를 복사할 때 "--main"을 지정할 수 없습니다.

-c, --compress

   디플레이트(deflate) 메서드로 파일을 압축하여, 출력 파일의 크기를 줄
   입니다. 기본적으로, 파일은 아카이브에 압축되지 않은 상태로 저장됩니
   다.

   아카이브를 복사할 때 "--compress"는 효과가 없습니다.

   Added in version 3.7.

--info

   진단 목적으로, 아카이브에 내장된 인터프리터를 표시합니다. 이 경우,
   다른 옵션은 무시되고 SOURCE는 디렉터리가 아닌 아카이브여야 합니다.

-h, --help

   간단한 사용법 메시지를 인쇄하고 종료합니다.


파이썬 API
==========

이 모듈은 두 개의 편의 함수를 정의합니다:

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

   *source*로 응용 프로그램 아카이브를 만듭니다. 소스는 다음 중 하나일
   수 있습니다:

   * 디렉터리 이름, 또는 디렉터리를 참조하는 *경로류 객체*. 이 경우 해
     당 디렉터리의 내용으로 새 응용 프로그램 아카이브가 만들어집니다.

   * 기존 응용 프로그램 아카이브 파일의 이름, 또는 이러한 파일을 참조
     하는 *경로류 객체*. 이 경우 파일이 대상(target)으로 복사됩니다
     (*interpreter* 인자에 제공된 값을 반영하도록 수정하면서). 필요하
     면, 파일 이름에 ".pyz" 확장자가 포함되어야 합니다.

   * 바이너리 모드에서 읽기로 열린 파일 객체. 파일의 내용은 응용 프로
     그램 아카이브여야 하며, 파일 객체는 아카이브의 시작 부분에 위치한
     것으로 가정합니다.

   *target* 인자는 결과 아카이브가 기록될 위치를 결정합니다:

   * 파일 이름이거나 *경로류 객체*이면, 아카이브가 그 파일에 기록됩니
     다.

   * 열린 파일 객체면, 그 파일 객체에 아카이브가 기록되며, 파일은 바이
     너리 모드로 쓰기로 열려 있어야 합니다.

   * target이 생략되면 (또는 "None"이면), 소스(source)는 디렉터리여야
     하며 대상은 ".pyz" 확장자가 추가된 소스와 이름이 같은 파일이 됩니
     다.

   *interpreter* 인자는 아카이브가 실행될 파이썬 인터프리터의 이름을
   지정합니다. 아카이브 시작 부분에 "셔뱅(shebang)" 줄로 기록됩니다.
   POSIX에서는 이를 OS가 해석하고, 윈도우에서는 파이썬 런처가 이를 처
   리합니다. *interpreter*를 생략하면 셔뱅 줄이 기록되지 않습니다.
   interpreter가 지정되고 target이 파일명이면, target 파일의 실행 가능
   비트가 설정됩니다.

   *main* 인자는 아카이브의 메인 프로그램으로 사용될 콜러블의 이름을
   지정합니다. 소스가 디렉터리이고 소스에 아직 "__main__.py" 파일이 없
   을 때만 지정할 수 있습니다. *main* 인자는 "pkg.module:callable" 형
   식이어야 하며 아카이브는 "pkg.module"을 임포트 하고 인자 없이 지정
   된 콜러블을 실행해서 실행됩니다. 소스가 디렉터리이고 "__main__.py"
   파일을 포함하지 않을 때 *main*을 생략하는 것은 에러입니다, 그렇지
   않으면 결과 아카이브가 실행 가능하지 않기 때문입니다.

   선택적 *filter* 인자는 추가되는 파일의 (소스 디렉터리에 상대적인)
   경로를 나타내는 Path 객체가 전달되는 콜백 함수를 지정합니다. 파일을
   추가하려면 "True"를 반환해야 합니다.

   선택적 *compressed* 인자는 파일을 압축할지를 결정합니다. "True"로
   설정하면, 아카이브의 파일이 디플레이트(deflate) 메서드로 압축됩니다
   ; 그렇지 않으면 파일이 압축되지 않은 상태로 저장됩니다. 기존 아카이
   브를 복사할 때는 이 인자가 효과가 없습니다.

   *source*나 *target*에 파일 객체가 지정되면, create_archive를 호출한
   후 파일 객체를 닫는 것은 호출자의 책임입니다.

   기존 아카이브를 복사할 때, 제공된 파일 객체에는 "read"와 "readline"
   또는 "write" 메서드만 필요합니다. 디렉터리에서 아카이브를 만들 때,
   대상이 파일 객체면 "zipfile.ZipFile" 클래스로 전달되며, 해당 클래스
   에 필요한 메서드를 제공해야 합니다.

   버전 3.7에서 변경: *filter*와 *compressed* 매개 변수를 추가했습니다
   .

zipapp.get_interpreter(archive)

   아카이브 시작 부분에서 "#!" 줄에 지정된 인터프리터를 반환합니다.
   "#!" 줄이 없으면, "None"을 반환합니다. *archive* 인자는 파일명이나
   바이너리 모드로 읽기로 열린 파일류 객체일 수 있습니다. 아카이브가
   시작 부분에 위치한 것으로 가정합니다.


예
==

디렉터리를 아카이브로 패킹하고, 실행합니다.

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

"create_archive()" 함수를 사용하여 같은 작업을 수행할 수 있습니다:

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

POSIX에서 응용 프로그램을 직접 실행할 수 있게 만들려면, 사용할 인터프
리터를 지정하십시오.

   $ python -m zipapp myapp -p "/usr/bin/env python"
   $ ./myapp.pyz
   <output from myapp>

기존 아카이브에서 셔뱅 줄을 바꾸려면, "create_archive()" 함수를 사용하
여 수정된 아카이브를 만드십시오:

   >>> import zipapp
   >>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')

파일을 제자리에서 갱신하려면, "BytesIO" 객체를 사용하여 메모리에서 치
환을 수행한 다음, 나중에 소스를 덮어씁니다. 파일을 제자리에서 덮어쓰면
에러로 인해 원본 파일을 손실할 위험이 있음에 유의하십시오. 이 코드는
이러한 에러에 대한 보호는 없지만, 프로덕션 코드는 이를 방지해야 합니다
. 또한, 이 방법은 아카이브가 메모리에 올라올 수 있을 때만 작동합니다:

   >>> import zipapp
   >>> import io
   >>> temp = io.BytesIO()
   >>> zipapp.create_archive('myapp.pyz', temp, '/usr/bin/python2')
   >>> with open('myapp.pyz', 'wb') as f:
   >>>     f.write(temp.getvalue())


인터프리터 지정하기
===================

인터프리터를 지정한 다음 응용 프로그램 아카이브를 배포한다면, 사용된
인터프리터가 이식성 있는지 확인할 필요가 있음에 유의하십시오. 윈도우
용 파이썬 런처는 가장 일반적인 POSIX "#!" 줄 형식을 지원하지만, 고려해
야 할 다른 문제가 있습니다:

* "/usr/bin/env python"(또는 "/usr/bin/python"과 같은 "python" 명령의
  다른 형식)을 사용한다면, 사용자에게 기본적으로 파이썬 2나 파이썬 3이
  있을 수 있음을 고려해야 하고, 두 버전에서 작동하도록 코드를 작성하십
  시오.

* "/usr/bin/env python3"과 같이 명시적인 버전을 사용하면 해당 버전이
  없는 사용자에게는 응용 프로그램이 작동하지 않습니다. (여러분의 코드
  를 파이썬 2 호환으로 만들지 않았다면 이것이 여러분이 원하는 것일 수
  있습니다).

* "파이썬 X.Y 이상"이라고 말할 방법이 없어서, "/usr/bin/env python3.4"
  처럼 정확한 버전을 사용할 때는 주의하십시오. 예를 들어 파이썬 3.5 사
  용자를 위해서는 셔뱅 줄을 변경해야 합니다.

일반적으로, 여러분의 코드가 파이썬 2나 3중 어느 것으로 작성되었는지에
따라 "/usr/bin/env python2"나 "/usr/bin/env python3"을 사용해야 합니다
.


zipapp으로 독립형 응용 프로그램 만들기
======================================

"zipapp" 모듈을 사용하면, 시스템에 적합한 버전의 파이썬만 설치되어있는
최종 사용자에게 배포 할 수 있는 필요한 모든 것이 담긴 파이썬 프로그램
을 만들 수 있습니다. 이 작업의 핵심은 응용 프로그램 코드와 함께 모든
응용 프로그램의 종속성을 아카이브에 묶는 것입니다.

독립형 아카이브를 만드는 단계는 다음과 같습니다:

1. 정상적으로 디렉터리에 응용 프로그램을 만드십시오, 그러면
   "__main__.py" 파일과 모든 지원 응용 프로그램 코드를 포함하는
   "myapp" 디렉터리를 얻게 됩니다.

2. pip을 사용하여 모든 응용 프로그램의 종속성을 "myapp" 디렉터리에 설
   치하십시오:

      $ python -m pip install -r requirements.txt --target myapp

   (이것은 "requirements.txt" 파일에 프로젝트 요구 사항이 있다고 가정
   합니다 - 그렇지 않으면, pip 명령 줄에 종속성을 수동으로 나열할 수
   있습니다).

3. 다음과 같이 응용 프로그램을 패키징하십시오:

      $ python -m zipapp -p "interpreter" myapp

그러면 독립형 실행 파일이 생성되며, 사용 가능한 적절한 인터프리터가 있
는 모든 시스템에서 실행할 수 있습니다. 자세한 내용은 인터프리터 지정하
기를 참조하십시오. 단일 파일로 사용자에게 제공될 수 있습니다.

유닉스에서, "myapp.pyz" 파일은 그대로 실행 파일입니다. "평범한" 명령
이름을 선호하면, 파일 이름을 변경하여 ".pyz" 확장자를 제거할 수 있습니
다. 윈도우에서, 파이썬 인터프리터가 설치될 때 ".pyz"와 ".pyzw" 파일 확
장자를 등록한다는 점에서  "myapp.pyz[w]" 파일은 실행 파일입니다.


경고
----

응용 프로그램이 C 확장을 포함하는 패키지에 의존하면, 해당 패키지는 zip
파일에서 실행할 수 없습니다 (이것은 OS 제한 사항인데, OS 로더가 로드
할 수 있으려면 실행 코드는 파일 시스템에 있어야만 합니다). 이 경우,
zip 파일에서 해당 종속성을 제외하고, 사용자가 파일을 설치하도록 요구하
거나, zip 파일과 함께 제공하고 "__main__.py"에 코드를 추가하여
"sys.path"에 압축 해제된 모듈을 포함하는 디렉터리를 포함할 수 있습니다
. 이 경우, 대상 아키텍처에 적합한 바이너리를 제공해야 합니다 (그리고
아마도 사용자 컴퓨터를 기반으로 실행 시간에 "sys.path"에 추가할 올바른
버전을 선택해야 합니다).


파이썬 Zip 응용 프로그램 아카이브 형식
======================================

파이썬은 버전 2.6부터 "__main__.py" 파일이 포함된 zip 파일을 실행할 수
있었습니다. 파이썬에서 실행되려면, 응용 프로그램 아카이브는 응용 프로
그램의 진입점으로 실행될 "__main__.py" 파일이 포함된 표준 zip 파일이어
야 합니다. 모든 파이썬 스크립트와 마찬가지로, 스크립트의 부모(이 경우
zip 파일)가 "sys.path"에 배치되므로 zip 파일에서 추가 모듈을 임포트 할
수 있습니다.

zip 파일 형식은 임의의 데이터를 zip 파일 앞에 추가할 수 있도록 합니다.
zip 응용 프로그램 형식은 이 기능을 사용하여 표준 POSIX "셔뱅(shebang)"
줄을 파일 앞에 추가합니다 ("#!/path/to/interpreter").

따라서 공식적으로 파이썬 zip 응용 프로그램 형식은 다음과 같습니다:

1. 문자 "b'#!'", 인터프리터 이름, 개행 ("b'\n'") 문자를 포함하는 선택
   적 셔뱅(shebang) 줄. 인터프리터 이름은 OS "셔뱅" 처리가 허용하는 모
   든 것, 또는 윈도우의 파이썬 런처일 수 있습니다. 인터프리터는 윈도우
   에서는 UTF-8로, POSIX에서는 "sys.getfilesystemencoding()"으로 인코
   딩되어야 합니다.

2. "zipfile" 모듈에 의해 생성된 표준 zip 파일 데이터. zipfile 내용은 *
   반드시* "__main__.py"라는 파일을 포함해야 합니다 (zip 파일의 "루트"
   에 있어야 합니다 - 즉, 서브 디렉터리에 있을 수 없습니다). zip 파일
   데이터는 압축되거나 그렇지 않을 수 있습니다.

응용 프로그램 아카이브에 셔뱅 줄이 있으면, POSIX 시스템에서 직접 실행
될 수 있도록 실행 파일 비트를 설정할 수 있습니다.

이 모듈의 도구를 사용하여 응용 프로그램 아카이브를 만들 필요는 없습니
다 - 모듈은 편의를 위한 것입니다. 하지만 어떤 방법으로 만들었든 위 형
식의 아카이브는 파이썬에서 허용됩니다.
