こういう物↓を作りました。
Docker Hubに上げたので、Dockerがあればそのまま使えます。
こんな事ができます。
$ docker run --rm s2terminal/lex-rank-summarizer \
'メロスは激怒した。必ず、かの邪智暴虐の王を除かなければならぬ と決意した。メロスには政治がわからぬ。メロスは、村の牧人である。笛を吹き、羊と遊んで暮して来た。けれども邪悪に対しては、人一倍に敏感であっ た。きょう未明メロスは村を出発し、野を越え山越え、十里はなれた此のシラクスの市にやって来た。メロスには父も、母も無い。女房も無い。十六の、 内気な妹と二人暮しだ。この妹は、村の或る律気な一牧人を、近々、花婿として迎える事になっていた。結婚式も間近かなのである。メロスは、それゆえ 、花嫁の衣裳やら祝宴の御馳走やらを買いに、はるばる市にやって来たのだ。先ず、その品々を買い集め、それから都の大路をぶらぶら歩いた。'
この結果が↓このように3行になります。
メロスは激怒した。
メロスは、村の牧人である。
きょう未明メロスは村を出発し、野を越え山越え、十里はなれた此のシラクスの市にやって来た。
PyPIにも上げましたので、$ pip install
しても使えます。
$ pip install s2terminal-lex-rank-summarizer
$ lex-rank-summarizer \
'メロスは激怒した。必ず、かの邪智暴虐の王を除かなければならぬ と決意した。メロスには政治がわからぬ。メロスは、村の牧人である。笛を吹き、羊と遊んで暮して来た。けれども邪悪に対しては、人一倍に敏感であっ た。きょう未明メロスは村を出発し、野を越え山越え、十里はなれた此のシラクスの市にやって来た。メロスには父も、母も無い。女房も無い。十六の、 内気な妹と二人暮しだ。この妹は、村の或る律気な一牧人を、近々、花婿として迎える事になっていた。結婚式も間近かなのである。メロスは、それゆえ 、花嫁の衣裳やら祝宴の御馳走やらを買いに、はるばる市にやって来たのだ。先ず、その品々を買い集め、それから都の大路をぶらぶら歩いた。'
要約の仕組み自体は、参考にさせていただいた下記の記事と同じでLexRankを使っています。
LexRankによる要約をCLIツールとして一発で使いたかったので、Pythonライブラリとして公開できる状態にしました。本稿では、このようなPythonでのCLIライブラリの開発・配布したときの方法をメモしていきます。
環境
- ChromeOS Crostini (Linux) Debian 10.10
- Docker version 20.10.7
Dockerしか使わないのでPythonはホストコンピュータにインストールしていませんが、今回Python 3.9.5を使っています。環境構築についてはこちらの拙稿で紹介した方法で、Docker内でPoetryを使ってやっています。
今回使ったDockerfile
とdocker-compose.yml
を貼っておきます。基本的に素のdockerコマンドは使わず$ docker-compose
を使って開発しています。
FROM python:3.9.5-slim AS base
WORKDIR /app
ENV PYTHONPATH /app/src:$PYTHONPATH
RUN pip install poetry
COPY pyproject.toml ./
COPY poetry.lock ./
RUN poetry config virtualenvs.in-project true
RUN poetry install --no-dev
FROM base AS dev
RUN apt-get update && apt-get install -y \
git \
vim \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN poetry install
CMD /bin/sh -c "echo 'docker dev ready'; while sleep 1000; do :; done"
version: '3'
services:
app:
build:
context: .
target: dev
volumes:
- .:/app
開発
$ poetry new --src
で初期化した環境で開発していきました。細かいソースコードはGitHubを読んでください。
Googleの公開しているpython-fireを使って、CLI引数を受け取ったりできるようにします。
from .summarize import generateSummary
import fire
def main():
fire.Fire(generateSummary)
tool.poetry.scripts
の設定を使って、CLIとして起動できるようにします。
[tool.poetry.scripts]
lex-rank-summarizer = "s2terminal_lex_rank_summarizer.main:main"
これで$ docker-compose run --rm app poetry run lex-rank-summarizer '要約したい文章'
でPythonプログラムを起動できるようになります。
Docker
Docker Hubに公開してCLIツールとして利用できる事を目指します。
CLIツールとして起動した時に引数だけを受け取ればいいように、ENTRYPOINT
を使って起動するようにしておきます。
ENTRYPOINT ["poetry", "run", "lex-rank-summarizer"]
動作するのを確認できたら、Docker Hubに公開します。$ docker push
してもいいのですが、Docker HubとGitHubを連携させて自動ビルド設定するのが楽ですし、READMEを自動で読み取ってDocker Hubのページにしてくれたりもします。
これでDocker Hubに登録されました。
これだけで$ docker run --rm s2terminal/lex-rank-summarizer "要約したい文章"
で使えるようになります。簡単ですね。
PyPI
PyPIへ公開して、$ pip install
して利用できる事を目指します。
こちらはPoetryがあれば楽です。参考にさせていただいた下記記事にほとんどすべて書いてあります。
実際にPyPIへ公開される時のメタデータはpyproject.toml
の中身を参考に埋め込まれるため、Poetryのドキュメントを参考にある程度記載しておきます。
license = "MIT"
readme = "README.md"
homepage = "https://github.com/s2terminal/lex-rank-summarizer"
repository = "https://github.com/s2terminal/lex-rank-summarizer"
ソースコードの準備ができたら公開の作業を進めていきます。まずTestPyPIに公開することで事前にテストできます。私の場合、pyproject.ymlの設定に誤りがあって開発時は動作するのにpublishしたものをpip install
して使うときだけ動かないという不具合があったのですが、そういった問題もTestPyPIを使うことで確認できます。
$ docker-compose run --rm app sh
# poetry build
# poetry config repositories.testpypi https://test.pypi.org/legacy/
# poetry publish -r testpypi
実際にTestPyPIから公開したライブラリをインストールして使ってみます。この開発環境のDockerを使ってもいいですし、適当に$ docker run --rm -it python:3.9.5-slim bash
とかで別の環境を作って試しても良いと思います。
# pip install s2terminal-lex-rank-summarizer --extra-index-url https://test.pypi.org/simple
# lex-rank-summarizer "こんにちは。"
問題が無ければ、本番のPyPIの方へpublishします。
$ docker-compose run --rm app poetry build
$ docker-compose run --rm app poetry publish
これでPyPIに登録されました。
まとめ
- CLIツールをDocker Hubで配布するのは簡単
- PyPIで配布するにはPoetryを使うと簡単