Mirai Translate TECH BLOG

株式会社みらい翻訳のテックブログ

ゼロから始めるPoetry

この記事は、みらい翻訳 Advent Calendar 2022 の2日目です。

こんにちは。プラットフォーム開発部のdiceです。
最近、わたしの所属チームでpipでのPythonライブラリ管理に苦労しており、Poetryというライブラリ管理ツールを使ってみたので、ご紹介します。

ライブラリ管理の苦労

pipでわずらわしく感じていたこと

  • lockファイルの生成に一手間かかる
  • 開発用とリリース用のrequirements.txtファイルが必要となる

Poetryとの出会い

いろいろ調べたところPoetryというツールで下記のように改善できそうということがわかりました。

  • lock ファイルの生成が容易
    • 依存するライブラリのバージョンも指定可能
  • テストライブラリを除くビルド、含むビルドが1ファイルで設定できる
    • 開発環境構築・リリース用コンテナ構築の設定ファイルが1つにまとめられる

Poetryとは

Pythonのライブラリ管理ツールです。(2019年12月にv1.0が公開されました)

python-poetry.org

github.com

プロジェクトが依存するライブラリをコマンドから管理(インストール/更新)することができます。

また、Poetry は繰り返しインストールできるようにロックファイルを提供し、配布用にプロジェクトをビルドすることができます。

システム要件

  • Python3.7以降
    今回は、Python3.9を使用します。
    実際にプロジェクト等で使用する場合には、pyenvを併せて使用する方が便利かと思います。

インストール方法

以下のコマンドを実行してインストールします。

Poetryのバージョンを指定する場合は、POETRY_VERSIONの環境変数を設定します。

$ curl -sSL https://install.python-poetry.org \
  | POETRY_VERSION=1.2.2 python3 -

プロジェクト作成方法

poetry-demo というプロジェクトを作成します。

$ poetry new poetry-demo

以下のようにプロジェクトが作成されます。

poetry-demo
├── README.md
├── poetry_demo              <-- プロジェクト名の"-"は"_"に変換されます
│   └── __init__.py
├── pyproject.toml
└── tests
    └── __init__.py

ディレクトリを移動します。

$ cd poetry-demo

今回は、poetry.lock ファイルを生成したいため以下のコマンドを実行します。

$ poetry install

poetry.lock ファイルが作成されます。

poetry-demo
├── README.md
├── poetry.lock
├── poetry_demo
│   └── __init__.py
├── pyproject.toml
└── tests
    └── __init__.py

ファイル内容

  • pyproject.toml
    tomlファイルのフォーマットは、PEP 518で定められています。
    https://peps.python.org/pep-0518/
    ファイル名・ファイルフォーマットは以下となります。
    (こちらはPoetry独自のファイルではありません)
[tool.poetry]
name = "poetry-demo"
version = "0.1.0"
description = ""
authors = ["Jone Doe <jone.doe@miraitranslate.com>"]
readme = "README.md"
packages = [{include = "poetry_demo"}]

[tool.poetry.dependencies]
python = "^3.9"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
  • poetry.lock
    依存するライブラリのバージョン情報等が記録されます。
    初期状態では、以下のような内容になっています。
package = []

[metadata]
lock-version = "1.1"
python-versions = "^3.9"
content-hash = "c595a0588c25d58f3e3834ad7169126836d262b925fe6ca9b5d540dcf301d254"

[metadata.files]

poetry_demo/main.py作成

試しに poetry_demo/main.py を新規作成して動作させます

def main():
    print("main!!")

if __name__ == "__main__":
    main()

実行

poetry_demo/main.py ができたら実行していきます。

まず、 PYTHONPATHを設定します。
(各自の環境に合わせて、"poetry-demoのパス名"を指定してください。)

$ export PYTHONPATH="/Users/jone/poetry-demo"

poetry runpython実行コマンドの頭につけることでPoetry仮想環境でプログラムが実行されます。

$ poetry run python poetry_demo/main.py

main!!

外部ライブラリを追加してみる

先ほど作成した poetry_demo/main.py を更新します。

外部ライブラリを使用しWEBページにアクセスするように変更します。

  • poetry_demo/main.py
import requests

def main():
    r = requests.get("https://example.com/")
    print(r.text)

if __name__ == "__main__":
    main()

外部ライブラリ(requests)追加

Poetry仮想環境に外部ライブラリを追加します。

$ poetry add requests

外部ライブラリ(requests)追加後の設定ファイル

  • pyproject.toml
[tool.poetry]
name = "poetry-demo"
version = "0.1.0"
description = ""
authors = ["Jone Doe <jone.doe@miraitranslate.com>"]
readme = "README.md"
packages = [{include = "poetry_demo"}]

[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.1"                             <-- 追加された設定

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
  • poetry.lock(一部)
    requests に関連する情報が追加されます。
    (依存するライブラリのバージョンも指定されます)
[[package]]
name = "requests"
version = "2.28.1"
description = "Python HTTP for Humans."
category = "main"
optional = false
python-versions = ">=3.7, <4"

[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<3"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<1.27"

実行

追加した外部ライブラリを使用しプログラムが実行できています。
(結果は省略してあります)

$ poetry run python poetry_demo/main.py

<!doctype html>
<html>
(省略)
</html>

単体テストについて

tests/test_main.py 作成

テスト実行用の tests/test_main.py を作成します。

from poetry_demo.main import main

def test_main():
    main()

pytestライブラリ追加

テスト用のライブラリ(pytest)を追加します。テスト用のライブラリは、mainプログラムで直接使用しているライブラリと分けて管理します。

下記のようにオプション --group dev を付加します。

$ poetry add pytest --group dev

テスト用ライブラリ追加後の設定ファイル

  • pyproject.toml
[tool.poetry]
name = "poetry-demo"
version = "0.1.0"
description = ""
authors = ["Jone Doe <jone.doe@miraitranslate.com>"]
readme = "README.md"
packages = [{include = "poetry_demo"}]

[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.1"

[tool.poetry.group.dev.dependencies]                 <-- 追加された設定
pytest = "^7.2.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

poetry.lock(一部)

pytestに関連する情報が追加されます。

[[package]]
name = "pytest"
version = "7.2.0"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"

テスト実行

追加したpytestライブラリでテストが実行できます。

$ poetry run pytest tests/test_main.py

========================================================================================== test session starts ===========================================================================================
platform darwin -- Python 3.9.5, pytest-7.2.0, pluggy-1.0.0
rootdir: /Users/jone/poetry-demo
collected 1 item                                                                                                                                                                                         

tests/test_main.py .                                                                                                                                                                               [100%]

=========================================================================================== 1 passed in 0.30s ============================================================================================

設定ファイルから環境構築

pyproject.toml , poetry.lock ファイルから別の環境に同一の実行環境を構築することができます。
ここでは以下の2つの例を紹介します。

開発環境等を作成する場合

テスト用ライブラリ含め全てのライブラリを入れて環境構築します。

$ poetry install

リリース用コンテナ環境等を作成する場合

テスト用ライブラリを除いて環境構築します。

$ poetry install --only main

おわりに

今回は、Poetryについて紹介しました。

pipなどでPythonのライブラリ管理に苦労されている方は、Poetryを使ってみてはいかがでしょうか。

また、Poetryは静的解析ツールの連携も可能なようですので今後試してみたいと思います。

みらい翻訳ではエンジニアを募集しています

みらい翻訳では、エンジニアを募集しています。

ご興味のある方は、ぜひ下記リンクよりご応募・お問い合わせをお待ちしております。

miraitranslate.com