All Articles

파이썬 package 배포 하기

Python은 가장 널리 쓰이는 언어중 하나고 오픈소스 라이브러리도 너무나 많으므로 당연히 오픈소스 배포과정이 쉽게 정리가 잘되어있을을것 같지만 의외로 헛갈리는 점들이 몇가지 있다. 알고나면 어렵지 않지만 처음 해보는 사람에게는 약간 혼동될수 있는 경우도 있으므로 정리를 해보기로 한다.

Steps

1 - setup.py 설정
setup.py파일을 프로젝트의 root 디렉토리에에 생성한다. 대부분의 빌드 설정을 setup.py 통해서 한다. setup.py파일을 통해 할수 있는 설정들은 여러가지가 있는데 그 중 가장 자주 쓰이는 설정들은 아래와 같다:

  • name: 프로젝트 이름
  • version: 배포 버젼
  • description: 프로젝트 설명
  • author: 프로젝트 저자
  • author_email: 저자의 이메일
  • url: 프로젝트 사이트 주소. 오픈소스의 경우 대부분 깃헙 주소를 사용한다.
  • download_url: 해당 라이브러리의 실행 바이너리 다운 받는 주소. 마찬가지로 오픈소소의 경우 대부분 깃헙의 archive주소를 설정한다.
  • install_requires: 해당 라이브러리를 사용하기 위해서 인스톨 되야하는 dependency들. 해당 라이브러리를 pip을 통해 인스톨 할때 이곳에 나열된 라이브러리들을 같이 인스톨 한다.
  • packages: 빌드에 포함들 package들. 한 프로젝트에 여러 package가 있을수도 있고 또한 빌드에서 제외할 package들 (예를 들어 test 코드나 doc 등등)이 있을수 있음으로 그러한 설정을 한다. 대부분 setuptools.find_packages 함수를 사용하여 자동으로 포함될 package들을 찾게 하고 대신에 제외되어야 할 package들을 exclude 인자를 통해 설정해준다.
  • keywords: 해당 프로젝트 관련 키워드.
  • python_requires: 서포트 하는 파이썬 버젼 설정.

    • 정확히 Python 3.6 에서만 실행된다면 : =3.6
    • Python 3 버젼 이상에서는 다 실행된다면 : >=3
  • package_data: 기본적으로 setup은 파이썬 파일만 빌드에 포함시킨다. 파이썬 파일 이 아닌 외부 파일을 포함시키기 위해선 포함시키고자 하는 파일들을 이 옵션에 명시해 줘야 포함된다. 그렇지 않으면 포함이 되지 않는다. 이 옵션 설정을 해주지 않거나 잘못 설정해주어서 문제가 생기는 경우가 꽤 있으니 주의하자.
  • zip_safe: 위의 package_data 설정을 하였으면 zip_safe 설정도 해주어야 하며 False로 설정해주어야 한다.
  • classifiers: PYPI에 등록될 메타 데이터 설정이다. 예를 들어 서포트 하는 python 버젼 정보를 명시할수 있다. 하지만 이건 PYPI에 등록될 메타 데이터일 뿐이고 실제 빌드에는 영향을 주지 않는다. 이점 주의하자.

이 외에도 많은 설정 옵션들이 있다. 모든 리스트는 이곳에서 볼 수 있다. 아래는 내가 최근에 배포한 오픈소스 라이브러리에 실제 사용된 setup.py 코드이다. 실제 코드는 이곳에서 볼 수 있다.

from setuptools import setup, find_packages

setup(
    name             = 'pyquibase',
    version          = '1.0',
    description      = 'Python wrapper for liquibase',
    author           = 'Eun Woo Song',
    author_email     = 'songew@gmail.com',
    url              = 'https://github.com/rampart81/pyquibase',
    download_url     = 'https://githur.com/rampart81/pyquibase/archive/1.0.tar.gz',
    install_requires = [ ],
    packages         = find_packages(exclude = ['docs', 'tests*']),
    keywords         = ['liquibase', 'db migration'],
    python_requires  = '>=3',
    package_data     =  {
        'pyquibase' : [
            'db-connectors/sqlite-jdbc-3.18.0.jar',
            'db-connectors/mysql-connector-java-5.1.42-bin.jar',
            'liquibase/liquibase.jar'
    ]},
    zip_safe=False,
    classifiers      = [
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.2',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6'
    ]
)

참고로 setuptools를 사용해 setup 설정을 하였으므로, 아직 setuptools가 인스톨 되어 있지 않다면 인스톨 하도록 한다.

pip install setuptools

2 - Setup.cfg

만일 README 파일이 마크다운 형태로 되어 있다면 setup.cfg 파일을 아래와 같이 설정 해준다.

[metadata]
description-file = README.md

3 - 빌드하기

빌드 하는 방법은 몇가지가 있지만 공식적으로는 wheel을 사용하여 빌드하는것이 권장된다. wheel은 build package인데 일반적인 source distribution보다 더 빨리 인스톨 되기에 공식적으로 권장된다. 아래 커맨드를 실행하여 wheel을 인스톨 하고 빌드를 하도록 하자.

pip install wheel
python setup.py bdist_wheel

위의 커맨드를 실행하면 dist 폴더가 생기고 그 안에 빌드 파일이 생성된다.

4 - 배포하기

이제 배포만 하면 된다. 배포는 twine을 사용해서 배포하도록 한다. python setup.py upload 커맨드를 사용하지 않고 twine을 사용하는 이유는 upload 커맨드는 일반 HTTP를 사용해서 배포하기 때문에 아이디나 패스워드가 노출될수 있는데 twineTLS를 사용하기 때문이다.

그리고 PYPI에 이미 계정이 있어야 하는데, 만일 PYPI 계정이 없다면 twine이 그 또한 가이드 해준다. 아래 커맨드를 사용하여 PYPI에 배포하자.

# 배포할 빌드 파일명이 pyquibase-1.0-py3-none-any.whl 라는 가정하에
twine upload dist/pyquibase-1.0-py3-none-any.whl

이제 pip install <package name>을 실행하여 팩케지를 어디서든 누구나 인스톨 할수 있다. 주의 할점은 인스톨은 곧바로 되어 검색은 PYPI가 인덱스 하는데 시간이 걸린다. 즉 pip search <package name>명령어를 치면 곧바로 검색이 안될수 있다. 배포한 package 관리는 PYPI 사이트에 로그인해서 해당 package의 페이지로 가면 된다.

Pro Tips

  • Distutils VS Setuptools

    • setup.py 설정을 하도록 해주는 라이브러리는 크게 distutilssetuptools 2가지가 있다. distutils는 파이썬의 기본 라이브러리에 포함이 되어있고 setuptools는 별도로 인스톨을 해야한다. 그래서 distutils를 사용하는게 default라고 생각할수 있지만 실제로는 setuptools를 사용하는게 default 이다. distutils의 단점들을 보완한게 setuptools라서 대부분 setuptools를 사용하고 있고 파이썬 공식 사이트에서도 setuptools를 권장하고 있다.
  • Package_data:

    • 만일 파이썬 파일이 아닌 다른 binary 파일을 포함해줘야 한다면 (예를 들어 jar 파일) setup.py 파일에서 package_data 설정을 꼭 해주어야 한다. 이 설정을 잘못하거나 하지 않으면 포함되어야 하는 파일들이 포함이 되지 않은체 빌드가 되서 작동이 잘 되지 않는 경우가 종종있다. 하지만 빌드는 성공하므로 문제가 생길때까지 몰르게 되는 경우가 많다.
    • zip_safeFalse로 같이 설정 해주어야 한다.
  • PYPI에 package를 업로드 한후 검색이 되기까지는 시간이 걸리므로 주의하자. 인스톨은 곧바로 된다.

빌드 설정 전체 코드 예제는 내가 최근에 배포한 오픈소스 라이브러리인 pyquibase에서 보고 참조 할수 있다.