AboutPython

[Python] 협업을 위한 코드 모듈화; setup.py

scone 2024. 10. 27. 23:01

파이썬 패키지 만들기: 협업을 위한 코드 모듈화

 

소개

협업 프로젝트에서 우리가 만든 코드를 다른 팀에서 쉽게 사용할 수 있도록 패키지화하는 방법에 대해 알아보겠습니다. 이를 통해 pip install package_name 형태로 간편하게 설치하고 사용할 수 있는 패키지를 만들 수 있습니다.

 

# 사전 설치
pip install setuptools

 

패키지 구조 만들기

package_name/
├── package_name/
│   ├── __init__.py
│   └── function.py
├── README.md
├── requirements.txt
└── setup.py

 

패키지 구조 설명

위의 패키지 구조는 Python 패키지를 만들기 위한 기본적인 틀입니다. 각 파일과 디렉토리가 어떤 역할을 하는지 하나씩 살펴보겠습니다.

  1. package_name/: 최상위 디렉토리로, 패키지의 이름을 따서 만듭니다. 이 디렉토리 안에 실제 코드가 들어갑니다.
  2. package_name/__init__.py: 이 파일은 패키지를 초기화하는 역할을 합니다. 이 파일이 있어야 Python이 이 디렉토리를 패키지로 인식합니다. (__version__ 을 통해 버전명을 명시해주는게 관례라고 합니다. 추후 버전 업데이트 이후에는 set.py와 version 명이 서로 같겠끔 같이 업데이트 해줍니다.)
  3. package_name/function.py: 여기에 실제로 사용할 함수나 클래스를 정의합니다. 예를 들어, 간단한 함수 하나를 정의해보겠습니다.
  4. setup.py: 이 파일은 패키지를 배포하고 설치하는 데 필요한 정보를 담고 있습니다. setup.py 파일의 예시는 다음과 같습니다.
from setuptools import setup, find_packages

setup(
    name="package_name",                # 패키지 이름
    version="0.1.0",                    # 버전
    description="A short description of your package", # 패키지 설명
    author="Your Name",                 # 작성자
    author_email="your.email@example.com",  # 작성자 이메일
    url="https://github.com/username/package_name", # 깃허브 저장소 URL
    packages=find_packages(),           # 패키지 찾기
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.6",           # Python 버전 요구사항
    install_requires=[                  # 의존성 패키지 목록
        "numpy>=1.19.0",
        "pandas>=1.1.0",
    ],
)

 

setup.py 파일은 패키지의 메타데이터와 의존성을 정의합니다. 주요 항목들은 다음과 같습니다:

  • name: pip가 참조하는 패키지 이름
  • version: 패키지 버전
  • author, author_email: 작성자 정보
  • description: 패키지에 대한 간단한 설명
  • url: 프로젝트 사이트 주소 (대부분 깃헙 주소를 사용한다.)
  • download_url: 소스 배포판의 다운로드 URL을 지정
  • packages: 패키지에 포함하거나 제외할 파일들을 선택하는 설정
  • classifiers: 패키지의 메타데이터를 분류하는 태그들로, Python 버전, 라이선스, 운영체제 등의 정보를 포함
  • python_requires: 패키지가 요구하는 최소 Python 버전을 지정
  • package_data: 기본적으로 setup은 파이썬 파일만 빌드에 포함시킨다. 파이썬 파일이 아닌 데이터 파일들(예: JSON, HTML, CSS 등)을 패키지에 포함시키기 위한 옵션이다.
  • zip_safe: 패키지가 ZIP 형식으로 설치되어도 안전한지를 나타내는 플래그, 일반적으로 package_data를 사용할 경우 False로 지정하고, 평소에도 False가 권장됩니다. (C 확장 모듈이 있는 경우, 런타임에 리소스 파일이 접근해야하는 경우, 패키지가 동적으로 파일을 찾아야하는 경우 False로 설정해야 합니다.)
  • install_requires: 패키지가 의존하는 다른 패키지들의 목록. pip install할 때, 여기에 나열된 라이브러리들을 같이 설치 합니다.

 

  • package_data 사용 예)
더보기
setup(
    ...
    package_data={
        'my_package': [
            'data/*.json',           # my_package/data/ 안의 모든 JSON 파일
            'templates/*.html',       # my_package/templates/ 안의 모든 HTML 파일
            'static/css/*.css',      # my_package/static/css/ 안의 모든 CSS 파일
        ],
    },
)

 

 

find_packages()는 setuptools에서 제공하는 함수로, 프로젝트 디렉토리 내의 모든 Python 패키지를 자동으로 찾아주는 유틸리티입니다. 이 함수는 다음과 같은 특징을 가집니다:

  1. __init__.py 파일이 있는 모든 디렉토리를 패키지로 인식합니다.
  2. 재귀적으로 하위 디렉토리까지 검색하여 모든 패키지를 찾습니다.
  3. 특정 디렉토리나 패키지를 제외하고 싶을 때는 exclude 파라미터를 사용할 수 있습니다.

만약 find_packages()를 사용하지 않는다면, 일일히 list로 넣어주어야 합니다.

  • exclude 옵션을 사용했을 때의 예)
더보기
from setuptools import setup, find_packages

setup(
    name='your-package',
    version='1.0.0',
    packages=find_packages(exclude=[
        'tests',                   # 테스트 디렉토리 제외
        'tests.*',                 # 테스트 패키지의 모든 하위 패키지 제외
        '*.tests',                 # 모든 패키지의 tests 서브패키지 제외
        '*.tests.*',              # tests 서브패키지의 모든 하위 패키지 제외
        'docs',                    # 문서 디렉토리 제외
    ]),
)

 

 

 

패키지 설치하기

로컬 설치 ( w/ Git Clone)

  1. # 패키지 디렉토리에서 pip install .
    • 패키지를 site-packages 디렉토리에 복사하여 설치합니다.
  2. # 패키지 디렉토리에서 pip install -e .
    • 패키지가 site-packages 디렉토리에 현재 위치에 대한 심볼릭 링크를 생성합니다.
    • 실제 코드는 원본 위치에 있게 됩니다.
    • 실시간으로 패키지에 대한 수정이 반영되는 효과가 있습니다. -> 개발 중인 패키지를 테스트할 때, 유리합니다.

로컬 설치 ( w/o Git Clone)

  • https를 통한 설치
    • 별도의 인증 설정이 불필요한 설치 방법 입니다.
    • github 계정에 대한 인증만 해주면 됩니다.
# 기본 설치
pip install git+https://github.com/username/repo.git

# 특정 브랜치 설치
pip install git+https://github.com/username/repo.git@develop

# 특정 태그 설치
pip install git+https://github.com/username/repo.git@v1.0.0

# 특정 커밋 설치
pip install git+https://github.com/username/repo.git@ad21f2c

 

 

  • ssh를 통한 설치
    • private 저장소 접근에 적합합니다.
    • SSH 키 기반 인증 입니다. (feat. ssh-keygen)
# 기본 설치
pip install git+ssh://git@github.com/username/repo.git

# 특정 브랜치
pip install git+ssh://git@github.com/username/repo.git@branch_name

# 특정 태그
pip install git+ssh://git@github.com/username/repo.git@v1.0.0

# 특정 커밋
pip install git+ssh://git@github.com/username/repo.git@commit_hash

 

 

PyPI에 패키지 등록하기

참고한 페이지: https://teddylee777.github.io/python/pypi/

 

사전에 https://pypi.org/ 사이트에 들어가 패키지 명이 겹치지는 않는지 확인해주어야 한다고 합니다. (회원 가입도 해주어야 합니다.)

 

  • wheel 파일(python 패키지의 배포 형식)을 만들어줍니다.
    • sdist는 소스배포판을 생성하는 명령어 입니다. 설치 시 빌드 과정이 필요합니다.
    • bdist_wheel은 wheel 배포판을 생성하는 명령어 입니다. 이미 빌드된 파일이기 때문에 컴파일이 불필요 합니다.
# 사전 준비
pip install wheel

# 소스 배포판(.tar.gz)과 wheel(.whl) 파일 생성
python setup.py sdist bdist_wheel

 

  • PyPI에 업로드
    • 업로드할 때, 아이디와 비밀번호를 물어봅니다.
# 사전 준비
pip install twine

# dist 안에 만들어진 배포판을 업로드 합니다.
python -m twine upload dist/*

 

 

 

Reference

- editable
https://draw-code-boy.tistory.com/m/602

- Pypi
https://teddylee777.github.io/python/pypi/

- 가이드문서
https://docs.python.org/ko/3.11/distutils/setupscript.html

- 그밖의 블로그
https://iambeginnerdeveloper.tistory.com/245