::: IT인터넷 :::

pyproject.toml을 이용한 파이썬 패키징 (2) - pyproject.toml의 등장

곰탱이푸우 2023. 9. 25. 08:20
지금까지 파이썬 프로젝트의 패키징은 setuptools의 setup.py를 사용하는 것이 일반적이었다.

 

setup.py를 사용한 파이썬 프로젝트 폴더 구성은 아래 문서를 참고한다.
setup.py를 사용한 파이썬 프로젝트의 예제 코드는 아래 문서를 참고한다.
그러나 현재는 pyproject.toml의 사용이 권장되고, setup.py 사용을 자제하는 것이 권고되고 있다.
따라서 기존 setup.py를 pyproject.toml로 변경해야 하며, 빌드와 배포에서도 변경이 필요하다.
 
pyproject.toml에 대해 알아보고 실제 코드에 적용하는 방법을 정리한다.
 
setup.py의 문제에 대해서는 아래 문서를 참고한다.
 

pyproject.toml의 등장

이러한 setup.py의 문제점을 해결하기 위해 2016년에 등장한 것이 pyproject.toml이다.
 

pyproject.toml 소개

pyproject.toml은 특정 도구에 종속되지 않는 선언적인 (declarative) 설정 파일을 제공한다.
 
PEP 517, PEP 518, PEP 621 등을 통해 파이썬 표준으로 정의되었다.
  • PEP 517 - Python 패키지에 대한 새로운 빌드 및 설치 패러다임
  • PEP 518 - Python 빌드 시스템과 pyproject.toml 정의
  • PEP 621 - pyproject.toml의 Metadata 스펙
 
특정 도구에 종속되지 않기 때문에 setuptools가 아닌 다른 도구를 사용해도 빌드가 가능하다.
아래와 같이 빌드 도구를 setuptools와 wheel을 명시할 수 있고, 다른 도구도 지정할 수 있다.
# pyproject.toml 예시
[build-system]
requires = ["setuptools>=42", "wheel"]
 
setup.py의 문제와 pyproject.toml 소개는 아래 문서에 잘 정리되어 있으므로 참고한다.

setuptools의 pyproject.toml

그렇다면 setuptools를 사용하면 안되는 것일까? 그렇지 않다.
파이썬 패키지의 빌드를 제공하는 도구는 poetry, flit 등이 있으며 setuptools도 pyproject.toml을 지원한다.
 
setuptools의 역할을 역할을 빌드 백엔드로 한정해서 계속 사용할 수 있다.
pyproject.toml을 작성하면서 build-system을 setuptools로 정의한다.
 
빌드 프론트엔드는 파이썬의 build 라는 라이브러리를 사용할 예정이다.
build 라이브러리는 pyproject.toml에 명시 된 빌드 정보들을 검증하고 빌드 백엔드인 setuptools를 호출한다.
whl 패키지가 생성되면 twine을 사용하여 저장소에 업로드하는 형태로 배포한다.
 
build와 twine 대신 다른 빌드 프론트엔드와 배포 도구를 사용해도 된다.
그리고 빌드 백엔드를 변경하려면 pyproject.toml의 build-system에 명시 된 setuptools를 다른 도구로 지정한다.
 
setuptools에서의 pyproject.toml 작성 방법은 아래 문서에 정리가 잘 되어 있다.
setuptools 61.0.0 이상의 버전을 사용해야 한다.
 
 

setuptools를 이용한 pyproject.toml 정의

setuptools에서 pyproject.toml을 정의하는 방법은 아래 문서를 참고한다.
실제 적용한 코드는 아래 부분에 작성한 'pyproject.toml로 변경하기' 항목을 참고한다.
 

setuptools의 pyproject.toml에서 패키지 경로 지정

패키지 내부 소스코드 파일의 경로 지정은 아래 문서를 참고한다.
src-laylout과 flat-layout을 언급하는데 차이점은 다음과 같다.
 
src-layout
소스코드 폴더를 명시적으로 지정한다.
패키지를 구성하는 모든 모듈의 코드들은 모두 src 폴더 하위에 작성한다.
project_root_directory
├─ pyproject.toml  # AND/OR setup.cfg, setup.py
├─ ...
├─ src/
│   └─ mypkg/
│       ├─ __init__.py
│       ├─ ...
│       ├─ module.py
│       └─ subpkg1/
│           ├─ __init__.py
│           ├─ ...
│           └─ module1.py
└─ tests/
    ├─ __init__.py
    ├─ ...
    ├─ test_module.py
... 생략 ...
 
 
flat-laylout
소스코드 폴더에 대한 명시적인 구분이 없다.
패키지를 구성하는 모듈의 코드들은 tests 폴더와 동일한 레벨에 구성한다.
project_root_directory
├─ pyproject.toml  # AND/OR setup.cfg, setup.py
├─ ...
├─ mypkg/
│   ├─ __init__.py
│   ├─ ...
│   ├─ module.py
│   └─ subpkg1/
│       ├─ __init__.py
│       ├─ ...
│       └─ module1.py
└─ tests/
    ├─ __init__.py
    ├─ ...
    ├─ test_module.py
... 생략 ...
 
일반적으로 다음과 같은 경우에 사용한다.
  • src-laylout - 규모가 크고 여러 모듈로 구성되는 패키지
  • flat-layout - 규모가 작고 적은 수의 모듈로 구성되는 패키지
 

setuptools의 pyproject.toml에서 의존성 설정

라이브러리와 파이썬 버전의 의존성 설정은 아래 문서를 참고한다.
setup.py의 아래 항목들이 바뀐 점을 주목한다.
  • install-requires가 dependencies로 변경
  • python-requires가 requires-python으로 변경
 

setuptools의 pyproject.toml 관련 변경 이력

pyproject.toml을 지원하기 위해 setuptools에 많은 변경이 발생했다.
 
자세한 변경 이력들은 아래 setuptools의 릴리즈 노트 (Change Log)를 참고한다.

빌드와 배포 도구 (build와 twine)

기존에 작성했던 setup.py 기반의 빌드와 배포 방법은 아래 문서를 참고한다.
일반적으로 사용되는 setup.py를 이용한 테스트, 빌드, 배포 스크립트는 다음과 같다.
# 테스트 (setup.py의 test_require에 pytest 지정 필요)
$ python setup.py test   

# 빌드와 배포
# bdist_wheel - whl 파일 생성
# upload -r - whl 파일 업로드
$ python setup.py bdist_wheel upload -r local
 
모두 setup.py를 실행하면서 전달 인자로 test, bdist_wheel, upload 등이 전달되는 것이 문제이다.
setup.py를 스크립트로 실행하는 형태이기 때문이다.
 
setup.py를 직접 실행하면 안되는 이유는 아래 문서를 참고한다.
따라서 명령 구문에서 setup.py를 실행하는 부분들을 모두 제거해야 한다.
테스트, 빌드, 배포 단계를 각각 나눠서 정리한다.
 
 

테스트

setup.py를 호출하는 명령은 파이썬 테스트 도구를 직접 실행하는 형태로 변경한다.
## 아래와 같이 되어 있다면
$ python setup.py test

## 아래와 같이 수정 (둘 중 하나 선택)
$ pytest    # 테스트를 수행하고 결과만 출력
$ pytest -srvA    # 테스트를 수행하고 모든 로그 출력
 

빌드

빌드를 위한 메타 데이터를 검증하고 빌드 백엔드를 호출하는 도구는 build 라이브러리를 사용한다.
해당 라이브러리에 대한 자세한 설명은 아래 문서를 참고한다.
wheel 파일을 생성하는 아래 명령도 build 라이브러리를 직접 실행하는 형태로 변경한다.
## 아래와 같이 되어 있다면
$ python setup.py bdist_wheel

## build 설치
$ pip install build

## 아래와 같이 수정 (둘 중 하나 선택)
$ python -m build -w    # -w는 whl만 생성
$ python -m build -w --no-isolation    # --no-isolation은 별도 파이썬 가상환경 미생성

 

만약 pyproject.toml의 build-system에 setuptools가 명시되어 있다면, setuptools가 whl 파일을 생성한다.
 
 

배포 (업로드)

생성 된 whl 패키지를 업로드하는 배포 도구는 twine을 사용한다.
해당 라이브러리에 대한 자세한 설명은 아래 문서를 참고한다.
wheel 파일을 업로드하는 아래 명령도 twine 라이브러리를 직접 실행하는 형태로 변경한다.
## 아래와 같이 되어 있다면
$ python setup.py upload local

## twine 설치
$ pip install twine

## 아래와 같이 수정
$ twine upload -r local dist/    # local 저장소의 dist/ 경로에 업로드
 
기존에 setup.py가 수행하던 업로드를 twine이 수행한다.
 

pyproject.toml로 변경하기

기존에 작성했던 setup.py를 pyproject.toml로 변경하고 빌드 스크립트에 반영하는 방법을 아래 문서를 참고한다.