일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- iterm2 shortcuts
- 도커
- zsh
- docker
- 테라폼 문법
- nosql
- Bash
- AWS
- customize
- iterm2 단축키
- Shell
- terraform
- 도커컴포즈
- server
- 파이썬
- docker-compose
- sftp란
- 컨테이너
- test
- BIG-O NOTATION
- linux
- Django
- 테라폼 기본 문법
- DynamoDB
- minikube 설치 방법
- zshrc
- terraform 문법
- minikube mac 설치
- python
- 빅오노테이션
- Today
- Total
sklass의 s-class 프로그래밍 blog
Project Packaging 본문
이번에는 자신의 Project를 packaging해서 PyPi에 올리기 전 TestPyPi에 등록하는 법을 배워보겠습니다. 우선 PyPi와 TestPyPi가 무엇인지부터 알아보겠습니다.
PyPi
PYPI는 Python Package Index의 줄임말로, 간단하게 파이썬 관련 패키지들이 모여있는 저장소(repository)라고 할 수 있습니다.
TestPyPi
TestPyPi는 PyPi에 자신의 project를 등록하기 전, 여러 테스트들을 진행해 볼 수 있는 임시 저장소라고 할 수 있습니다.
모듈(Module)과 패키지(Package)
project를 생성하기전, module과 package, 그리고 project가 파이썬에서 어떤 의미를 가지는지 먼저 확인해보겠습니다.
모듈(Module)은 파이썬에서 재사용이 가능한 기본 단위로, .py라는 확장자를 갖는 단일 파일에 작성되며, 여러 모듈들은 다시 패키지(Package)라는 단위로 관리됩니다. 파이썬의 디렉토리에 __init__.py 파일이 존재하면 이를 패키지라고 여깁니다. 또 이러한 패키지들이 여럿 모여 프로젝트(Project)의 형태를 가지게 됩니다.
1.1 Project 생성
그럼 간단한 project를 생성해보겠습니다. 아래와 같은 파일구조로 project를 생성해주세요.
packaging_tutorial/
└── src/
└── example_package/
├── __init__.py
└── example.py
__init__.py는 example_package라는 디렉토리를 패키지로 import하기 위해서 꼭 추가해주어야하는 파일로, 빈 파일로 두면 됩니다. 따라서, example_package는 __init__.py파일이 존재하는 디렉토리 임으로, 패키지이고, example.py는 모듈이라고 보면 되겠습니다. 또한, packaging_tutorial은 example_package라는 package와 example.py 라는 module이 한데 모인 프로젝트라고 할 수 있습니다.
1.2 example.py 모듈
그럼 이제 example.py에 아래의 코드를 추가해줍니다.
def add_one(number):
return number + 1
1.3 배포에 필요한 파일들 추가
아래의 파일 구조로 파일들을 생성하세요.
packaging_tutorial/
├── LICENSE
├── pyproject.toml
├── README.md
├── setup.cfg
├── src/
│ └── example_package/
│ ├── __init__.py
│ └── example.py
└── tests/
test/는 test파일들을 위한 디렉토리로 지금은 비워두면 됩니다.
1.4 pyproject.toml 생성
pyproject.toml은 pip 이나 build 같은 build tools를 명시하는 곳으로, 저희는 setuptools를 사용해보겠습니다. pyproject.toml에 아래의 내용을 적어주세요.
[build-system]
requires = [
"setuptools>=42",
"wheel"
]
build-backend = "setuptools.build_meta"
build-system.requires는 패키지를 build할 때 필요한 패키지들을 나열하는 곳으로, build를 하는동안에만 사용 가능한 패키지들입니다. (install이 된 뒤에는 사용 가능하지 않습니다.)
build-system.build-backend는 build를 수행하기 위한 Python object의 이름으로, setuptools를 사용하는 이번 튜토리얼에서는 위와 같이 적용하면 됩니다. (flit이나 poetry를 사용하는 경우에는 다른 내용을 적용시켜야합니다.)
1.5 metadata 생성
metadata는 아래와 같이 총 2가지가 존재합니다.
- Static metadata (setup.cfg): 언제든 같은 내용의 정적 metadata입니다. Dynamic metadata에 비해 간단하고, 가독성이 좋으며, Dynamic metadata처럼 encoding error를 발생 시키지 않습니다.
- Dynamic metadata (setup.py): 가변적인 metadata로, install-time마다 값이 바뀌는 extension modules나 extensions to setuptools는 setup.py를 이용하는게 좋습니다.
위의 내용과 같이 Dynamic metadata를 필연적으로 써야하는 상황이 오지 않는 이상, Static metadata (setup.cfg)를 쓰는것이 바람직합니다.
그럼, setup.cfg에 아래의 내용을 적으세요.
[metadata]
name = example-pkg-YOUR-USERNAME-HERE
version = file: src/hits/VERSION
author = Example Author
author_email = author@example.com
description = A small example package
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/pypa/sampleproject
project_urls =
Bug Tracker = https://github.com/pypa/sampleproject/issues
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent
[options]
package_dir =
= src
packages = find:
python_requires = >=3.6
[options.packages.find]
where = src
name의 값은 unique해야함으로, 당신의 이름이나 혹은 특별한 값을 주어서 적용해서 다른 사용자들이 PyPi에 올린 이름과 겹치지 않게 해야합니다.
1.6 README.md 생성
위의 metadata에 내용에서 알 수 있듯이, long_description이 README.md를 참조하고 있습니다. 따라서, README.md는 sdist( Source Distribution) 을 만들기 전에 코드에 추가되어야하는데, 최신 setuptools는 README.md를 자동으로 코드에 추가해줍니다.
그럼 아래의 내용을 README.md에 적으세요.
# Example Package
This is a simple example package. You can use
[Github-flavored Markdown](https://guides.github.com/features/mastering-markdown/)
to write your content.
1.7 LICENSE 생성
license를 포함하는것이 PyPi에 업로드 되는 모든 패키지들에 굉장히 중요한 부분입니다. 이번 튜토리얼에서는 MIT license를 사용하는데, 만약 다른 license를 적용하고 싶다면 https://choosealicense.com/ 여기서 확인해보면 됩니다.
LICNESE에 아래의 내용을 입력하세요.
Copyright (c) 2018 The Python Packaging Authority
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
1.8 Source Distribution 코드에 파일 추가
1.6에서 봤듯이, README.md는 metadata에서 참조하고 있기때문에, sdist을 만들기 전에 코드에 꼭 필요한 파일입니다. 하지만 최신 setuptools는 README.md를 포함시켜주어, 아무런 문제가 되지 않지만, 만약 README.md말고 다른 파일, 예를 들어 버전을 명시하는 파일을 metadata가 참조하고 있다면, 이는 setuptools가 자동으로 코드에 포함시켜주지 않습니다. 이렇게 sdist를 만들기 전 꼭 필요한 파일들을 코드에 추가해주려면, MANIFEST.in 을 프로젝트에 추가해주면 됩니다. README.md는 자동으로 추가되지만, 예시를 위해 README.md와 version정보를 가지고 있는 VERSION이라는 파일을 MANIFEST.in을 이용해 코드에 추가해 주겠습니다.
MANIFEST.in에 아래와 같이 입력하세요
include README.md
include src/hits/VERSION
VERSION은 아래와같이 입력하면 됩니다.
0.0.1
1.9 Distribution Archives 만들기
이제 이번 튜토리얼의 packaging_tutorial 디렉토리의 distribution packages을 만들어 보겠습니다. 이 archive들은 PyPi에 업로드도고 pip을 이용해서 install가능합니다.
우선 아래의 명령어로 PyPA를 최신 버전으로 업그레이드 해줍니다.
$ python3 -m pip install --upgrade build
그 후, pyproject.toml이 위치한 디렉토리에서 아래의 명령어를 실행합니다.
$ python3 -m build
위의 명령어를 실행하면 아래와 같이 dist라는 폴더와 2개의 파일이 생깁니다.
dist/
example_package_YOUR_USERNAME_HERE-0.0.1-py3-none-any.whl
example_package_YOUR_USERNAME_HERE-0.0.1.tar.gz
1.10 Distribution Archives를 TestPyPI에 업로드
우선, TestPyPI의 계정을 만들어야 합니다. TestPyPI의 계정은 PyPI의 계정과는 별개의 계정임으로, PyPI에 업로드 할 때에는 다시 PyPI 계정을 만들어주어야합니다. TestPyPI 계정은 https://test.pypi.org/account/register/ 여기서 계정을 만들면 됩니다.
계정을 만들었다면, API token을 발행해야합니다. Token이 발행되면 다시는 볼 수 없으므로, 무조건 복사해서 메모해두어야합니다.
TESTPyPI의 API token은 https://test.pypi.org/manage/account/#api-tokens 여기서 발행하면됩니다.
이제 twine을 이용해서 distribution package를 TestPyPI에 업로드 해보겠습니다.
아래의 명령어를 project.toml이 위치한 디렉토리에서 실행하세요.
$ python3 -m pip install --upgrade twine
그리고 아래의 명령어를 이용해서 dist아래의 archives를 업로드하세요.
$ python3 -m twine upload --repository testpypi dist/*
위 명령어를 실행하면, username과 password를 물어보는데, username은 __token__, password는 위에서 발행한 API token을 붙혀넣어주면 됩니다.
1.11 Installation (pip install)
아래의 명령어로 --index-url의 값을 test.pypi로 명시해주고, --no-deps로 PyPI에는 있지만 TestPyPI에는 없어서 에러를 일으킬 수 있는 dependency를 다운 받지않는 옵션을 주어서 install 할 수 있습니다.
$ python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps example-pkg-YOUR-USERNAME-HERE
만약, 위의 옵션이 조금 복잡하게 느껴진다면 아래의 명령어로 간단하게 설치해도 됩니다.
$ pip install -i https://test.pypi.org/simple/ example-pkg-YOUR-USERNAME-HERE==0.0.1
1.11 다음 단계..
이제 TestPyPI에 패키지를 업로드하는데에 성공했습니다. 하지만 TestPyPI는 temporary한 공간으로, 테스트를 목적으로하는 repository입니다. Permanent 하게 업로드하고 싶다면 PyPI에 업로드해야합니다.
TestPyPI에서 테스트를 완료한 패키지를 PyPI에 업로드하고 싶다면, 아래의 내용들을 꼭 기억해서 업로드하세요.
- 기억하기 쉽고 unique한 이름을 패키지에 지어주세요. 이번 튜토리얼처럼 자신의 이름을 패키지 이름으로 지정해줄 필요는 없습니다.
- https://pypi.org 계정을 만드세요. 위에서도 말했듯이, TestPyPI와 PyPI는 두개의 다른 서버(test server, main server)에서 운영되고 있기 때문에 계정정보가 공유되지 않습니다. 따라서 PyPI에 올릴때에는 다시 계정을 만들어야합니다.
- 패키지를 업로드 할 때, 위와 같이 --repository 옵션에 testpypi를 값으로 줄 필요가 없습니다. 아래의 명령어로 twine을 이용해서 업로드하면 됩니다.
$ twine upload dist/*
- 이제 pip install을 할 때, --index-url이나 --no-deps와 같은 옵션 없이, 아래의 명령어로 업로드된 패키지를 pip install을 하면 됩니다.
$ python3 -m pip install [your-package]
References
https://packaging.python.org/tutorials/packaging-projects/#setup-args
Packaging Python Projects — Python Packaging User Guide
setup.cfg is the configuration file for setuptools. It tells setuptools about your package (such as the name and version) as well as which code files to include. Eventually much of this configuration may be able to move to pyproject.toml. Open setup.cfg an
packaging.python.org
'python' 카테고리의 다른 글
Black formatter (0) | 2021.12.16 |
---|---|
conda 명령어 정리 (0) | 2021.11.14 |
Python 정적 메소드 @classmethod, @staticmethod (1) | 2021.10.24 |
shutil (0) | 2021.09.28 |
Celery (0) | 2021.09.01 |