파이썬 - PyPI 패키지 만들기 (2) long_description, cmdclass 옵션
지난 글에 이어,
파이썬 - PyPI 패키지 만들기
; https://www.sysnet.pe.kr/2/0/12863
약간의 옵션을 좀 더 정리해보겠습니다.
우선, 이전의 setup.py로는,
from setuptools import setup, find_packages
import netutil
setup(
name="net-util",
description="utility functions for networking",
version=netutil.__version__,
author=netutil.__author__,
author_email="techsharer@outlook.com",
url="https://www.sysnet.pe.kr",
license="Ms-PL",
packages=find_packages(exclude=[]),
install_requires=["requests>=2.22.0"],"
)
PyPI에 올렸을 때 소개가 이렇게 비어 있습니다.
이 부분을 채우려면, long_description 속성을 채우면 되는데요, 재미있게도 어차피 setup.py가 파이썬 스크립트 파일이기 때문에 함수를 이용해 처리하는 것도 가능합니다.
...[생략]...
def readme():
with open('README.md', 'rb') as f:
return f.read().decode('utf-8')
setup(
name="net-util",
description="utility functions for networking",
long_description=readme(),
long_description_content_type='text/markdown',
...[생략]...
install_requires=["requests>=2.22.0"],
)
또한, 해당 텍스트는 text/plain, text/x-rst, text/markdown 형식을 지원하므로 원하는 것을 선택해 파일로 만들어 두면 됩니다. 그래서 대충 이렇게 README.md를 만들어 두면,
# net-util
패키지 테스트를 위해 만든 예제 프로젝트입니다.
```python
>>> import netutil
>>> print(netutil.iputil.get_public_ip())
220.127.177.110
```
## Installing net-util and Supported Versions
net-util is available on PyPI:
```console
$ python -m pip install netutil
```
https://pypi.org/project/net-util/에서 그 결과를 확인할 수 있습니다. ^^
setup.py에서 좀 특별한 옵션이라면 바로 기존 패키징 코드를 사용자 정의할 수 있는 cmdclass 옵션입니다. 이 옵션을 활용하면 "python setup.py [cmd]"에 해당하는 명령어의 "[cmd]" 작업을 사용자 정의할 수 있습니다. 가령 [cmd]로 bdist_wheel을 사용하는 경우라면, 다음과 같이 bdist_wheel 작업을 확장할 수 있습니다.
import netutil
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
from setuptools import setup, find_packages
class UserCode(_bdist_wheel):
def run(self):
print('pre-process ===============================================')
_bdist_wheel.run(self)
print('post-process ==============================================')
setup(
name="net-util",
description="utility functions for networking",
long_description=readme(),
long_description_content_type='text/markdown',
cmdclass={'bdist_wheel': UserCode},
...[생략]...
)
그럼 실행 시 다음과 같은 결과를 확인할 수 있습니다.
C:\temp> python setup.py bdist_wheel
running bdist_wheel
pre-process ===============================================
running build
running build_py
installing to build\bdist.win-amd64\wheel
running install
running install_lib
creating build\bdist.win-amd64\wheel
creating build\bdist.win-amd64\wheel\netutil
...[생략]...
adding 'netutil/network_logger.py'
adding 'net_util-1.0.0.2.dist-info/METADATA'
adding 'net_util-1.0.0.2.dist-info/WHEEL'
adding 'net_util-1.0.0.2.dist-info/top_level.txt'
adding 'net_util-1.0.0.2.dist-info/RECORD'
removing build\bdist.win-amd64\wheel
post-process ==============================================
위의 경우 단순히 pre/post 처리를 했지만
고급스럽게는 해당 [cmd] 작업의 내부 단계들을 가로채서 사용자 정의하는 것도 가능합니다.
사실 저런 식의 pre/post 작업이라면 그냥 단순하게 setup(...) 호출의 앞/뒤로 코드를 수행해도 유사한 결과를 얻습니다. (혹은, 아예 빌드 스크립트 차원에서 "python setup.py ..." 호출 전/후에 처리해도 되고.)
print('pre-process ===============================================')
setup(
name="net-util",
description="utility functions for networking",
long_description=readme(),
long_description_content_type='text/markdown',
# cmdclass={'bdist_wheel': UserCode},
...[생략]...
)
print('post-process ==============================================')
참고로, cmdclass는 결국 "[cmd]"에 따라 달라지기 때문에 배포 패키징 명령어가 바뀐다면 그에 맞게 조정해야 합니다. 예를 들어 "python setup.py sdist"로 하는 경우라면 아래와 같이 코드가 바뀌게 됩니다.
from distutils.command.sdist import sdist as _sdist
class UserCode(_sdist):
def run(self):
_sdist.run(self)
setup(
name="net-util",
description="utility functions for networking",
long_description=readme(),
long_description_content_type='text/markdown',
cmdclass={'sdist': UserCode},
...[생략]...
)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]