Poetry事始め
ごく簡単なCLIアプリケーションの一連の作成手順を通して,Pythonプロジェクト管理ツールPoetryの基本的な使用方法をまとめる.
実行環境はMacOS/Ubuntuを想定.
Poetryのバージョンは1.0.5
ゴール
以下のように動作するgreet
コマンドを作成する.
コマンドに必要なPythonパッケージを管理したり,ローカルの仮想環境にコマンドをインストールして使用できるようにしたりするためPoetryを使用する.
$ greet hello John
Hello John!
$ greet goodnight John
Goodnight John...
$ greet goodnight --sleeping John
zzz
補足
Poetryを使用してローカル環境に直接パッケージをインストールするのは少し厄介.
簡単なので題材をCLIツールとしたが,これを普段使い用にPoetryでインストールするいい方法がわからなかった.
詳しくは本稿末 "Poetryの設定" の項目を参照してください.
Poetry
Pythonプロジェクトで使用するパッケージの依存関係やバージョンを管理するためのツール
(ここではパッケージを作成するために必要なディレクトリ構成とファイルをまとめてプロジェクトと呼ぶ).
pyproject.tomlファイルをもとにパッケージの情報を管理するので,pyproject.tomlファイルを共有すればプロジェクトに必要な環境を簡単に再現できる.pyproject.tomlファイルの雛形もPoetryが自動的に作成する.
公式では
Poetry is a tool for dependency management and packaging in Python. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you.
Poetryのインストール
予めPyenvが使用可能であるとインストール時のトラブルが少なくて良い,
以降の説明ではPythonの実行をpython
コマンドによるものとする.
MacOS/Linuxの場合,以下でPoetryをインストールする.
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
MacOSの場合はsource ~/.bashrc
,Ubuntuの場合はsource ~/.profile
を実行してpoetry
コマンドのパスを通す.
poetry -h
を実行してきれいなヘルプが出力されればOK.
python3
コマンドでのPoetryのインストールは本稿末の "python3コマンドでのPoetryのインストール" の項目を参照してください.
新規Pythonプロジェクトの作成
Poetryのnew
コマンドで新規Pythonプロジェクトを作成する.
任意の場所でpoetry new greet
を実行し,新規Pythonプロジェクトgreet
を作成.
greet
パッケージを作成するために必要なファイル一式が自動的に作成される.
greet
├── greet
│ └── __init__.py
├── pyproject.toml
├── README.rst
└── tests
├── __init__.py
└── test_greet.py
pyproject.toml
後述するpoetry install
でプロジェクトからパッケージを作成する際に使用される.
コマンド実行時,よく見ているとPoetryが一時的にsetup.pyを作成しているのがわかる.
[tool.poetry.dependencies], [tool.poetry.dev-dependencies]でプロジェクトで使用するパッケージのリストとそのバージョンが列挙されている.
依存するパッケージのインストール時に自動的にアップデートされる.
Pythonパッケージのインストール
add
コマンドでプロジェクトで使用するPythonパッケージをインストールできる,
デフォルトではvirtualenv
でプロジェクト用の仮想環境が自動的に作成され,その中にインストールされる.
greet
ツールでは以下のPythonのパッケージを使用する.
- 動作に必須のパッケージ
- cleo
- 開発中のみ使用するパッケージ(dev用)
- flake8
- autopep8
pyproject.toml
のあるgreet
ディレクトリで以下を実行する.
poetry add cleo
poetry add --dev flake8 autopep8
dev用はadd
コマンドに--dev/-D
オプションをつけてインストールする.
これにより,poetry install
でプロジェクトのパッケージ(ここではgreet
パッケージのこと)をインストールする際,--no-dev
オプションを指定して実行に必要のないパッケージのインストールをスキップできる.
補足1
Ubuntuでpoetry add ...
を実行して次のようなエラーが出る場合は,エラーメッセージの通りapt-get install python3-venv
を実行すると正常に動作するようになる.
Creating virtualenv greet-b6grBBry-py3.6 in /root/.cache/pypoetry/virtualenvs
The virtual environment was not created successfully because ensurepip is not
available. On Debian/Ubuntu systems, you need to install the python3-venv
package using the following command.
apt-get install python3-venv
You may need to use sudo with that command. After installing the python3-venv
package, recreate your virtual environment.
Failing command: ['/root/.cache/pypoetry/virtualenvs/greet-b6grBBry-py3.6/bin/python', '-Im', 'ensurepip', '--upgrade', '--default-pip']
補足2
VSCodeを使用している場合は,VSCodeで使用するPythonインタプリタにPoetryで作成された仮想環境のものを選択すること.
仮想環境のパスはpoetry env info
のPathで確認できるのでそれを指定.
例えば以下の場合,/root/.cache/pypoetry/virtualenvs/greet-b6grBBry-py3.6
を指定.
$ poetry env info
Virtualenv
Python: 3.6.9
Implementation: CPython
Path: /root/.cache/pypoetry/virtualenvs/greet-b6grBBry-py3.6
Valid: True
System
Platform: linux
OS: posix
Python: /usr
greetツールの実装
pyproject.tomlのあるgreet
ディレクトリでpoetry shell
を実行し,本プロジェクト用の仮想環境に入る.
greet/greet
ディレクトリに以下のapplication.pyを作成.
CleoはPythonのCLI用パッケージであり,コマンドやオプションを簡単に追加できるほか,出力もきれいに配色されたものにできる.Poetryも使用している.
from cleo import Command, argument, option, Application
class HelloCommand(Command):
name = 'hello'
description = 'Say hello to someone'
arguments = [argument('name', 'Name of a person to hello')]
def handle(self):
self.line(f'Hello {self.argument("name")}!')
class GoodnightCommand(Command):
name = 'goodnight'
description = 'Say goodnight to someone'
arguments = [argument('name', 'Name of a person to goodnight')]
options = [option('sleeping', 's', 'Sleeping...')]
def handle(self):
if self.option('s'):
self.line('zzz')
else:
self.line(f'Goodnight {self.argument("name")}...')
application = Application()
application.add_commands(HelloCommand(), GoodnightCommand())
def main():
application.run()
pyproject.tomlファイルの編集
pyproject.tomlファイルに以下を追記.
[tool.poetry.scripts]
greet = 'application:main'
[tool.poetry.scripts]
はsetuptoolsのentry_pointsにあたるもので,<command_name> = '<module_name>:<function_name>'
のように指定する.
これにより,greetコマンドを実行したときapplication.pyのmain関数が実行される.
greetパッケージの作成・インストール
pyproject.tomlのあるgreet
ディレクトリでpoetry install
を実行する.
poetry install --no-dev
とした場合,dev用パッケージはインストールされない.
開発目的ではpoetry install
を使用し,パッケージを使用するだけであればpoetry install --no-dev
を使用する.
greetコマンドの動作確認
冒頭のゴールに示したように,仮想環境内で以下のようにgreet
コマンドが実行できる.
$ greet hello John
Hello John!
$ greet goodnight John
Goodnight John...
$ greet goodnight --sleeping John
zzz
greet -h
を実行すると,Cleoによって配色されたきれいなヘルプが見れるはず.
以上が本稿の趣旨.
Appendix
python3コマンドでのPoetryのインストール
python
コマンドがない状態(/usr/bin
にpython
がなく,python3
のみの状態)を想定.
python3
コマンドを使用している場合は以下でインストールことができる.
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3
必要であれば,echo 'alias python="python3"' >> ~/.bashrc && source ~/.bashrc
を実行してPython3をpython
コマンドで実行可能にしてからcurl ... python
でPoetryをインストールできる.
しかし,いずれの場合もインストール後にパスを通した後も以下のエラーでPoetryが実行できない.
/usr/bin/env: ‘python’: No such file or directory
原因は,Poetryは実行される際インストールに使用されたインタプリタを使用するが, ~/.poetry/bin/poetry
の1行目に#!/usr/bin/env python
がハードコーディングされており,python3
でインストールした場合も/usr/bin/python
を使用しようとするためで,これを#!/usr/bin/env python3
に書き換えれば正常に使用できる.
(issue: https://github.com/python-poetry/poetry/issues/1543)
python
コマンドがない状態(/usr/bin
にpython
がなく,python3
のみの状態)の解決策として,ln -s /usr/bin/python3 /usr/bin/python
でシンボリックリンクを作成してからcurl ... python
でPoetryをインストールしても問題なく動作する.
ほかにも,python
コマンドでPython2を,python3
コマンドでPython3を実行している場合は注意が必要.
Pyenvを使用し,3系に切り替えてPoetryをインストールするのが一番トラブルが少ないと思われる.
Poetryを使用した複数人での開発
pyproject.tomlファイルをリポジトリで共有することで,開発環境を揃えることができる.
開発に新規参加する場合,リポジトリをcloneした後,pyproject.tomlファイルのあるディレクトリでpoetry install
を実行するだけで,このPythonプロジェクト用の仮想環境が切られ,その中に必要なパッケージがインストールされる.
Poetryの設定
poetry config --list
でPoetryの設定が列挙される.
設定項目 | デフォルト値 | 説明 |
---|---|---|
virtualenvs.create | true |
poetry add やpoetry install の実行時,仮想環境を使用するかどうか.falseにした場合直環境に作用するため注意.例えば,falseの状態でpoetry install --no-dev を実行すると,pyproject.tomlに列挙されたdev用パッケージが直環境からアンインストールされる. |
virtualenvs.in-project | false |
poetry virtualenvs.in-project true でtrueに設定できる.仮想環境用のファイルがプロジェクト内に作成されるようになる.これにより,プロジェクトのディレクトリを削除したとき仮想環境も同時に削除できる. |
ローカル環境に直接パッケージをインストールするにはvirtualenvs.create
をfalseにすれば良いが,poetry install --no-dev
でパッケージをインストールすると,ローカル環境からdev用パッケージがアンインストールされてしまう.
一方,poetry install
でパッケージをインストールするとdev用パッケージの不要なものまでインストールされてしまうので,ローカル環境全体に渡って使用するパッケージをPoetryでインストールするのは難しい.いい方法があったら教えてください.