본문 바로가기
CS

[Python] Pypi에 패키지 업로드하기

by cuda 2023. 1. 22.

보다 깊은 공부도 할 겸, 재미도 있어 보여서 Numpy만으로 구성한 딥러닝 프레임워크 비슷하게 만들어보게 되었다.

깃허브에는 올리긴 했는데, 이어서 Pypi에도 업로드하여 pip install로 다운로드할 수 있으면 좋을 것 같아서, 해당 코드를 업로드해 보았다.

 

 

나의 경우에는 neuralflow라는 이름의 패키지를 만들었는데, 이를 Pypi에 업로드하기 위해서는 다음과 같은 구성으로 만들어줘야 한다.

맨 위에 상위 폴더가 존재하고, 그 아래에, build, dist, neuralflow, neuralflow.egg-info, LICENSE, README.md, setup.py가 구성되어 있는 모습이다.

이 중에서 build, dist, neuralflow.egg-info는 추후 언급할 단계에서 자동적으로 생성되기 때문에 패스하고, 나머지 요소들에 대해 하나씩 다뤄보도록 하겠다.

(neuralflow의 이름을 가지고 있는 디렉토리는 "패키지 이름 디렉토리" 라는 이름으로 부르도록 하겠다.)

 

패키지 이름 디렉토리

위 사진을 보면 패키지 이름을 가진 디렉토리는 두 가지임을 확인할 수 있다.

여기서, 상위 디렉토리 안에 포함되어 있는 하위 패키지 이름 디렉토리는, 우리가 파이썬에서 import를 할 때 저 디렉토리의 이름으로 import를 하게 된다.

예를 들어, 딥러닝 프레임워크를 cpu 버전과 cuda 버전으로 나누고 싶을 때, pip상에서 설치할 때 다음과 같이 분화하고 싶다고 해보자.

 

# cpu only
pip install neuralflow-cpu

# use cuda
pip install neuralflow

 

 

이렇게 pip 상으로는 다른 이름을 가지고 있지만, 설치한 뒤에도 저 이름 그대로 import를 해야 한다면 어떨까? 매우 불편할 것이다.

# 옳은 예시
from neuralflow.model import Model


# 다음과 같이 import시 불편함
from neuralflow-cpu.model import Model

이러한 불편함이 발생하지 않도록 import시 명시하는 패키지의 이름이 하위 패키지 이름 디렉토리인 것이다.

즉, 상위 디렉토리의 이름과 추후 설명할 setup.py에서 이름을 다르게 하여 다양한 버전으로 pip에 다르게 등록하여도,

하위 패키지 이름을 동일하게 해 놓으면 해당 패키지를 설치한 이후에는 어떠한 버전을 사용하더라도 같은 패키지 이름으로 사용할 수 있다.

실제로, 이번에 패키지를 업로드하면서, cpu 버전을 따로 업로드하였고, 해당 패키지의 디렉토리는 다음과 같이 구성되어 있다.

내부에 위치한 패키지 이름 디렉토리가 같음을 확인할 수 있다.

 

LICENSE, README.md

이 부분은 간단하다. LICENSE는 말 그대로 LICENSE에 대해 명시해 놓으면 되고(MIT, Apache... 등등) README.md는 깃허브 리드미와 동일하게 해당 패키지에 대한 명세를 적어놓으면 된다.

 

 

setup.py

이 부분이 복잡하기도 하고, 가장 중요하기도 하다.

우선, 해당 파일 예시를 같이 살펴보면서 알아가 보자.

 

import setuptools
from setuptools import setup

# long description을 README.md로 대체하기 위한 작업
with open("README.md", "r") as fh:
    long_description = fh.read()

setup(

	# module 이름
    name='', 
    
    # version 명시
    version='0.0.1',
    
    # package에 대한 짧은 description
    description='',
    
    # package에 대한 자세한 description
    # README.md로 대체한다
    long_description=long_description,
    long_description_content_type="text/markdown",
    
    # package 저자 이름
    author='',
    
    # package 저자 이메일 
    author_email='',
    
    # package url (ex: github)
    url='',
    license='MIT',
    packages=setuptools.find_packages(),
    
    # 파이썬 버전
    python_requires='>=3.8',  
    
  	# package 설치 시 필요한 다른 package
    # 이렇게 설정해놓은 package들은 설치 시 자동으로 설치된다.
    install_requires = [
        "matplotlib==3.6.3",
        "matplotlib-inline==0.1.6",
        "numpy==1.24.1",
        "packaging==23.0",
        "pandas==1.5.3",
        "pickleshare==0.7.5",
        "Pillow==9.4.0",
        "tqdm==4.64.1"
    ],
    classifiers = [
                      "Programming Language :: Python :: 3",
                      "License :: OSI Approved :: MIT License",
                      "Operating System :: OS Independent"
    ]
)

여기서는 따로 주의할 점은 없고, module 이름인 name의 값과 상위 패키지 이름 디렉토리의 이름을 같게 설정해야 한다.

각자의 package에 맞춰 알맞게 수정한 뒤, 저장하면 1차적인 준비는 끝이 난다.

 

여기까지 작성이 완료되었으면 업로드 절차를 진행해야 한다.

 

업로드

 

 

우선, Pypi에 회원가입이 되어있지 않으면 가입부터 진행한다.

 

PyPI · The Python Package Index

The Python Package Index (PyPI) is a repository of software for the Python programming language.

pypi.org

 

이후, setuptools와 wheel 모듈을 설치한다.

$ pip install setuptools wheel

이후, 터미널의 경로를 setup.py가 있는 경로로 옮겨준 뒤, 터미널에 다음과 같이 입력한다.

$ python setup.py sdist bdist_wheel

그러면 build, dist, egg-info 디렉토리가 생성됨을 확인할 수 있다.

여기서 주의할 점은, 버전을 바꿔서 업로드할 때 기존 build, dist, egg-info는 지우고 빌드 명령어를 입력하는 것이 좋다.

만약 그대로 둔 상태에서 실행하게 되면, 기존 버전도 재업로드가 되는 현상이 발생한다.

물론, 상관은 없지만, 개인적으로 지우고 빌드한 뒤 업로드하는 것을 선호한다.

 

이후, twine 모듈을 설치한다.

$ pip install twine

그런 다음 아래의 명령어를 입력하면 업로드가 진행된다.

$ python -m twine upload dist/*

그러면 다음과 같이 username과 password를 입력하라고 하는데, 이때에는 Pypi username과 password를 입력해 주면 된다.

Uploading distributions to https://upload.pypi.org/legacy/
Enter your username: 
Enter your password:

 

이후, 성공적으로 업로드가 되었다면 해당 패키지의 링크를 반환하고, 해당 링크를 접속해 보면 본인의 패키지가 성공적으로 업로드됨을 확인할 수 있다.

다만, 기존 패키지와 이름이 비슷하거나, 같을 경우에는 업로드가 제한될 수 있는데, 이 경우에는 패키지의 이름을 바꾼 뒤 위의 업로드 과정을 다시 거쳐서 업로드해야 한다.

이러한 수고로움을 제거하기 위해, 업로드 전에 Pypi에 본인이 업로드하고자 하는 패키지 이름을 검색해 보고, 유사한 이름이 없을 경우에 업로드하는 것이 좋을 것 같다.

 

댓글