파이썬에서 작업한 소스를 공개/비공개 배포하기 위해서 패키징을 하는 방법을 요약, 정리했다.
파이썬 모듈 배포하기
이 글은 setuptools, builds 그리고 PyPI 업로드를 위한 twine 를 사용하고 있다.
[핵심 용어]
- PyPi, Python Package Index: 파이썬 사용자를 위한 오픈소스 패키지의 공개 저장소 일명 PyPi
- PyPa, 파이썬 패키징 위원회: 표준 패키징 도구/메타 데이터/파일 형식 표준을 GitHub 와 Bitbucket 을 통해서 여러 패키징 도구, 문서, 이슈 추적기를 관리하고 있다.
- distutils: 1998년/파이썬 표준 라이브러리 최초의 빌드 및 배포 시스템. 대부분 직접 사용이 단계적으로 폐지되고 있다.
- distutils는 파이썬 3.10부터 deprecated, 3.12에서 삭제될 예정.
- setuptools : 2004 공개/ distutils 의 드롭인(drop-in) 대체품. distutils 와 큰 차이는 다른 패키지에 대한 의존성을 선언할 수 있다.
- [pyproject.toml]: 2016년 setuptools의 메타 파일 setup.py 의존성을 피하고자 독립한 빌드용 선언적 메타정보 파일.
- wheel: distutils/setuptools 에 bdist_wheel 명령을 추가하는 프로젝트이다. 파이썬 라이브러리를 바이너리 확장을 포함/크로스 플랫폼 바이너리 패키징 형식 지원 (“휠”,”휠 파일”, PEP 427 정의).
도구 설치
setuptools 기반 배포도구 설치
1 | python -m pip install setuptools wheel twine |
파이썬 패키징
https://packaging.python.org/en/latest/tutorials/packaging-projects/ 내용을 요약, 정리, 보충한다.
프로젝트 생성
패키징 수행하면 별도의 가상환경을 생성해서 진행한다.
프로젝트를 패키징하는 과정을 위해서 packaging_tutorial 폴더 아래에 같은 구조를 갖는다.
1 | packaging_tutorial/ |
example_package_YOUR_USERNAME_HERE
: 프로젝트 이름이고 중복하지 않게 한다.__init__.py
: 빈 파일로 폴더를 패키지로 인식하게 한다.example.py
: 모듈.
example.py
모듈 소스.
1 | def add_one(number): |
패키징용 파일 생성
배포를 위한 프로젝트의 구성을 위해 패키징에 필요한 파일을 추가한 구조는 아래 같다.
1 | packaging_tutorial/ |
LICENSE
: 라이센서 선언pyproject.toml
: 프로젝트 배포 프로젝트 생성에 사용하는 프론트엔드 빌드도구pip
, 백엔드 밸드도구build
README.md
tests/
: 테스트 파일용 공간. Leave it empty for now.
패키징의 프론트엔드, 백엔드는 참조의 5번 항목을 살펴보자.
pyproject.toml
구성
보통 파일 내용은 아래 항목으로 구성한다. 이 파일은 TOML 형식의 구조를 따르고 있다. 여기에 대해서는 아래 참조 4번 항목 내용을 보기 바란다.
1 | [build-system] |
빌드 도구를 명시하는 명세서 pyproject.toml
에 setuptools 를 사용한 예이다.
1 | [build-system] |
requires
: 빌드용 도구 지시.build-backend
: 프론트엔드 (pip)에서 빌드에 사용하는 백엔드 도구
다음은 Hatching 이란 빌드 도구를 사용한 예이다.
1 | [build-system] |
메타 정보를 포함한 간단한 pyproject.toml
구성 결과.
1 | [build-system] |
자세한 메타 정보 내역은 프로젝트 메타정보 정의를 참조한다. 주요 메타 정보의 인자:
[project]
:- requires-python : 패키지가 요구하는 최소 파이썬 버전 명시
- classifiers: pip가 인지하는 패키지에 대한 정보
README.md / LICENSE 파일
README.md 파일에 패키지 모듈를 설명한다.
1 | # Example Package |
LICENSE 파일에 저작권을 명시한다.
1 | Copyright (c) 2018 The Python Packaging Authority |
배포 묶음 생성하기
배포를 위한 build 도구를 설치한다.
1 | python3 -m pip install --upgrade build |
packaging_tutorial
폴더 아래 pyproject.toml 파일이 있는 위치에서 배포를 위한 build 명령으로 소스를 패키징을 한다.
build 를 수행하면 별도의 venv 가상환경을 생성해서 의존성에 명시된 setuptools 등을 설치하고 빌드를 진행한다.
1 | python3 -m build |
이 명령의 결과로 dist
폴더에 우리 프로젝트에 대한 배포용 패키징으로 소스 패키징 .gz
파일, built distribution 패키징 .whl
2개의 파일이 생성된다.
1 | dist/ |
pip 로 wheeels 설치하기
pip 에서 built distribution 파일을 직접 설치할 수 있다. installing-from-wheels 참조.
다음은 우리 프로젝트의 wheel 패키징을 설치한다.
1 | python -m pip install example_package_YOUR_USERNAME_HERE-0.0.1-py3-none-any.whl |
혹은 provides_extras 메타 정보를 사용해 추가 설치를 한다면,
1 | python -m pip install './somepackage-1.0-py2.py3-none-any.whl[my-extras]' |
Upload
처음 PyPi 에 업로드를 하려면 아래 2가지 단계를 거쳐서 진행해 본다.
- https://test.pypi.org/account/register/ 에서 등록
- 실제 pypi 가 아닌 튜토리얼과 테스트를 위한 곳.
- PyPi 업로드를 완성하려면 PyPI API token 을 발급받아야 한다.
PyPI에 업로드가 완료되면 pip 를 통해서 패키지를 설치할 수 있다. 업로드를 위해서 Twin 패키지를 설치하고 사용해야 한다.
1 | python3 -m pip install --upgrade twine |
twine 모듈을 사용해서 dist/ 아래의 모든 소스/휠 패키징 묶음을 업로드할 수 있다. 지금은 testpypi
에 업로드를 해보자.
1 | python3 -m twine upload --repository testpypi dist/* |
- 업로드시 username은
__token__
사용. - 패스워드는 발급받은
pypi-
으로 시작하는 token 값.
업로드 진행은 아래 같을 것이다.
1 | Uploading distributions to https://test.pypi.org/legacy/ |
여기서 repository로 testpypi 를 지정했으므로 업로드한 결과는 다음 같이 확인할 수 있다.
https://test.pypi.org/project/example_package_YOUR_USERNAME_HERE
저장소에서 설치하기
위에 testpypi 에 업로드한 패키지를 설치하려면 아래 같이 --index-url
로 저장소를 지정해서 사용한다.
1 | python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps example-package-YOUR-USERNAME-HERE |
PyPI 에 업로드
마지막으로 실제 패키지를 PyPI에 업로드하려면 https://pypi.org 등록을 하고, 등록한 사용자 아이디를 사용하고 --repository
인자를 제외하고 업로드하면 된다.
1 | python3 -m twine upload dist/* |
통합 메타 정보로서 pyproject.toml
활용
테스트, 코드 포맷팅 등에 대한 정보로 활용한다. 대표적으로는 코드 포맷팅 도구인 black, 테스트용 프레임워크인 pytest 등이 pyproject.toml에 설정 값을 저장하고 있다 - 파이썬 패키징의 역사, blog
1 | # pyproject.toml of black |
다음
이후에 다른 빌드 도구들, 테스트 도구들을 다뤄보자.