LoginSignup
0
0

自作Packageで共通処理を切り出してpip installで複数プロジェクトで使い回す(Python, Hatchling)

Posted at

背景

  • 複数のアプリで利用される共通処理を自作Packageで切り出して利用したい
  • 以下のようにリポジトリ内に複数アプリから共通して使われるパッケージを用意します
  • common_slackという自作パッケージを用意します
.
├── README.md
├── common
│   ├── common_slack
│   │   ├── __init__.py
│   │   └── slack.py
├── app_A
│   ├── Dockerfile
│   ├── main.py
└── app_B
    ├── Dockerfile
    ├── main.py
  • Python, Pipenv, Hatchlingを使った環境で進めていきます

なんでわざわざパッケージ化するの? 普通にimportじゃダメなの?

  • Dockerコンテナ化するときに、app_A, app_Bの外側のディレクトリを考慮するのが面倒なので、build済みwheelを対象プロジェクトに配置して、pip installで管理できるようにしていきます

Hatchling? SetupTools?

BuildのBackendシステムとしてはHatchlingを使います. SetupToolsも有名ですが、よりモダンなBuildのBackendシステムということでhatchlingを採用しました.

用語を整理していきます.

Build Backend

source tree や source destricutionを受け取り、wheelやsource districutionをビルドするライブラリ. 例: Hatchling, Setuptools

Build Frontend

ユーザーがwheelやsource distributionをビルドするために使うツール. 実際のビルドはBuild Backendに委譲する. 例: pip, build

手順

  • 1 . packageの実装
  • 2 . packageのビルド
    • pyproject.tomlの用意
    • build
  • 3 . projectAからの呼び出し

最終的に以下のようなディレクトリ構成になります.

.
├── common
│   ├── common_slack
│   │   ├── __init__.py
│   │   └── slack.py
│   ├── dist
│   │   ├── common_slack-0.0.1-py3-none-any.whl
│   │   └── common_slack-0.0.1.tar.gz
│   ├── pyproject.toml
│   ├── requirements.txt
├── projectA
│   ├── Dockerfile
│   ├── main.py
│   ├── requirements.txt
└── projectB
    ├── Dockerfile
    ├── main.py
    ├── requirements.txt

1. packageの実装

まずは common/common_slack/slack.py の実装

import requests
import json

class Slack:

    def post_message(self, title: str, message: str, channel_id: str) -> None:
        requests.post(
            url='https://slack.com/api/chat.postMessage',
            headers={
                'Authorization': f'Bearer xxx',
                "Content-Type": "application/json"
            },
            data=json.dumps({
                'channel': channel_id,
                "attachments": [
                    {
                        "color": color,
                        "title": title,
                        "text": message,
                    }
                ]})
        )
        return

common/common_slack/__init__.py の実装

from ai_sier_core.slack import Slack
__all__ = ('Slack')

2. packageのビルド

pyproject.tomlの用意

common/pyproject.toml でpackageの設定をしていきます.

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "common_slack"
version = "0.0.1"
authors = [
  { name="Suzuki Shogo", email="xxx@jp" },
]
description = "common slack library"
readme = "README.md"
requires-python = ">=3.8"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]
dependencies = ['requests']
  • [project].nameはpackageの名前です. この名前と-packageの親ディレクトリのpathが一致している必要があります. また、nameがcommon-slack の場合は pathは common_slackで探索されるので注意してください.
  • packageの依存関係を作りたい場合は、dependenciesに書いてください.

build

cd common/common_slack
python3 -m pip install --upgrade build
python3 -m build

すると、common/dist以下に wheelの生成物であるcommon_slack-0.0.1-py3-none-any.whl と source distributionの生成物である common_slack-0.0.1.tar.gz が出力されます.

3. projectAからの呼び出し

pip installする

以下のコマンドで生成したwheelをinstallします

cd project_A
pip install ../common/dist/common_slack-0.0.1-py3-none-any.whl
# pipenvの場合
# pipenv run pip install ../common/dist/common_slack-0.0.1-py3-none-any.whl
main.py
from common_slack import Slack

Slack().post_message('title', 'description')

これで共通処理を複数PJから呼び出せます.
Packageを更新した場合は、buildしなおして、呼び出し側がpip installしなおせば反映されます.

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0