背景・目的
Poetryを最近触れる機会があったので、あらためて知識の整理と簡単な動作を確認してみます。
まとめ
下記に特徴をまとめます。
特徴 | 説明 |
---|---|
Poetry | Python で依存関係を管理およびパッケージ化するためのツール プロジェクトが依存するライブラリを宣言でき、ライブラリが管理 (インストール/更新) される Poetry は、繰り返しインストールを確実にするためのロックファイルを提供し、配布用にプロジェクトを構築できる |
System requirements | Python 3.8以上が必要 |
Project setup | - |
プロジェクトを作成する | poetry new <プロジェクト名>により可能 |
Python Version | 他のパッケージとは異なり、Poetry は Python インタープリターを自動的にインストールしない パッケージ内の Python ファイルをスクリプトやアプリケーションのように実行したい場合は、それらを実行するための独自の Python インタープリターを使用する必要がある pyproject.tomlに定義する |
関連パッケージの依存関係の定義 | 下記の方法がある。 ・tool.poetry.dependenciesに記載する ・ poetry add pendulum コマンドを実行する |
poetry.lockファイル | 依存関係が記録される リポジトリで共有することでプロジェクト関係者で同一の環境を利用できる |
概要
下記を基に整理します。
Introduction
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 offers a lockfile to ensure repeatable installs, and can build your project for distribution.
- Poetry は、Python で依存関係を管理およびパッケージ化するためのツール
- プロジェクトが依存するライブラリを宣言でき、ライブラリが管理 (インストール/更新) される
- Poetry は、繰り返しインストールを確実にするためのロックファイルを提供し、配布用にプロジェクトを構築できる
System requirements
Poetry requires Python 3.8+. It is multi-platform and the goal is to make it work equally well on Linux, macOS and Windows.
- Python 3.8以上が必要
- Linux、macOS、Windows で動作
Basic usage
下記を基に整理します。
Project setup
poetry new
により、プロジェクトを作成します。
- プロジェクトを作成します
poetry new poetry-demo
- 実行すると下記の通りディレクトリが作成されます
poetry-demo ├── pyproject.toml ├── README.md ├── poetry_demo │ └── __init__.py └── tests └── __init__.py
重要なのは、pyproject.tomlファイル。これを使用するとプロジェクトとその依存関係が調整されます。
[tool.poetry]
name = "poetry-demo"
version = "0.1.0"
description = ""
authors = ["Sébastien Eustace <sebastien@eustace.io>"]
readme = "README.md"
packages = [{include = "poetry_demo"}]
[tool.poetry.dependencies]
python = "^3.7"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Poetry は、パッケージにプロジェクトのルートにある tool.poetry.name と同じ名前のパッケージが含まれていると想定します。そうでない場合は、tool.poetry.packages にパッケージとその場所を指定します。
Setting a Python Version
Unlike with other packages, Poetry will not automatically install a python interpreter for you. If you want to run Python files in your package like a script or application, you must bring your own python interpreter to run them.
- 他のパッケージとは異なり、Poetry は Python インタープリターを自動的にインストールしない
- パッケージ内の Python ファイルをスクリプトやアプリケーションのように実行したい場合は、それらを実行するための独自の Python インタープリターを使用する必要がある
Poetry will require you to explicitly specify what versions of Python you intend to support, and its universal locking will guarantee that your project is installable (and all dependencies claim support for) all supported Python versions. Again, it’s important to remember that – unlike other dependencies – setting a Python version is merely specifying which versions of Python you intend to support.
- Poetry では、サポートする Python のバージョンを明示的に指定する必要がある
- そのユニバーサル ロックにより、プロジェクトがインストール可能 (およびすべての依存関係がサポートを要求) であることが保証され、サポートされているすべての Python バージョンがサポートされる
- 他の依存関係とは異なり、Python バージョンの設定は、サポートする Python のバージョンを指定するだけである
- pyproject.tomlファイルの該当箇所を載せます
[tool.poetry.dependencies] python = "^3.7.0"
- 3.7.0 より新しいバージョンの Python 3 であれば、どれでも使用できる
When you run poetry install, you must have access to some version of a Python inrepreter that satisfies this constraint available on your system. Poetry will not install a Python interpreter for you. If you use a tool like pyenv, you can use the experimental configuration value virtualenvs.prefer-active-python.
- poetry install を実行する場合、システムで使用できるこの制約を満たす Python インタプリタのバージョンにアクセスできる必要がある
- Poetry は Python インタプリタをインストールしない
- pyenv などのツールを使用する場合は、実験的な構成値 virtualenvs.prefer-active-python を使用できる
Initialising a pre-existing project
Instead of creating a new project, Poetry can be used to ‘initialise’ a pre-populated directory. To interactively create a pyproject.toml file in directory pre-existing-project:
- 新しいプロジェクトを作成する代わりに、Poetry を使用して、事前に設定されたディレクトリを「初期化」できる
Operating modes
Poetry can be operated in two different modes. The default mode is the package mode, which is the right mode if you want to package your project into an sdist or a wheel and perhaps publish it to a package index. In this mode, some metadata such as name and version, which are required for packaging, are mandatory. Further, the project itself will be installed in editable mode when running poetry install.
If you want to use Poetry only for dependency management but not for packaging, you can use the non-package mode:
In this mode, metadata such as name and version are optional. Therefore, it is not possible to build a distribution or publish the project to a package index. Further, when running poetry install, Poetry does not try to install the project itself, but only its dependencies (same as poetry install --no-root).
- 2 つの異なるモードで操作できる
- デフォルトのモードはパッケージ モード
- プロジェクトを sdist または Wheel にパッケージ化し、場合によってはパッケージ インデックスに公開する場合に使用する
- パッケージ化に必要な名前やバージョンなどの一部のメタデータが必須
- プロジェクト自体は、インストールを実行すると編集可能モードでインストールされる
- 非パッケージモード
- 名前やバージョンなどのメタデータはオプション
- ディストリビューションをビルドしたり、プロジェクトをパッケージ インデックスに公開したりすることはできない
- poetry install を実行すると、Poetry はプロジェクト自体をインストールせず、その依存関係のみをインストールする (poetry install --no-root と同じ)
- デフォルトのモードはパッケージ モード
Specifying dependencies
If you want to add dependencies to your project, you can specify them in the tool.poetry.dependencies section.
- プロジェクトに依存関係を追加する場合は、tool.poetry.dependency セクションで依存関係を指定できる
[tool.poetry.dependencies]
pendulum = "^2.1"
As you can see, it takes a mapping of package names and version constraints.
Poetry uses this information to search for the right set of files in package “repositories” that you register in the tool.poetry.source section, or on PyPI by default.
Also, instead of modifying the pyproject.toml file by hand, you can use the add command.
- パッケージ名とバージョン制約のマッピングが必要
- この情報を使用して、tool.poetry.dependenciesセクション、デフォルトPyPIに登録したリポジトリ内の適切なファイルセットを検索する
- pyproject.toml ファイルを手動で変更する代わりに、add コマンドを使用することも可能
poetry add pendulum
Using your virtual environment
By default, Poetry creates a virtual environment in {cache-dir}/virtualenvs. You can change the cache-dir value by editing the Poetry configuration. Additionally, you can use the virtualenvs.in-project configuration variable to create virtual environments within your project directory.
There are several ways to run commands within this virtual environment.
-
デフォルトでは、Poetry は {cache-dir}/virtualenvs に仮想環境を作成する
-
Poetry 構成を編集することで、cache-dir 値を変更できる
-
virtualenvs.in-project 構成変数を使用して、プロジェクト ディレクトリ内に仮想環境を作成することもできる
-
仮想環境内でコマンドを実行する方法はいくつかある
Using poetry run
To run your script simply use poetry run python your_script.py. Likewise if you have command line tools such as pytest or black you can run them using poetry run pytest.
- スクリプトを実行するには、poetry run python your_script.py を使用する
- pytest や black などのコマンド ライン ツールをお持ちの場合は、poetry run pytest を使用して実行できる
Activating the virtual environment
The easiest way to activate the virtual environment is to create a nested shell with poetry shell.
To deactivate the virtual environment and exit this new shell type exit. To deactivate the virtual environment without leaving the shell use deactivate.
- 仮想環境をアクティブにする最も簡単な方法は、poetry shellを使用してネストされたシェルを作成すること
- 仮想環境を非アクティブにしてこの新しいシェルを終了するには、
exit
と入力する - シェルを終了せずに仮想環境を非アクティブ化するには、
deactivate
する
Version constraints
In our example, we are requesting the pendulum package with the version constraint ^2.1. This means any version greater or equal to 2.1.0 and less than 3.0.0 (>=2.1.0 <3.0.0).
- 例) バージョン制約 ^2.1 を持つpendulumパッケージをリクエストする
- 2.1.0 以上 3.0.0 未満 (>=2.1.0 <3.0.0) のバージョンを意味する
How does Poetry download the right files?
When you specify a dependency in pyproject.toml, Poetry first takes the name of the package that you have requested and searches for it in any repository you have registered using the repositories key. If you have not registered any extra repositories, or it does not find a package with that name in the repositories you have specified, it falls back to PyPI.
When Poetry finds the right package, it then attempts to find the best match for the version constraint you have specified.
- Poertryが適切なファイルをダウンロードする方法
- pyproject.toml で依存関係を指定すると、Poetry はまず要求したパッケージの名前を取得する
- repositories キーを使用して登録したリポジトリ内でそのパッケージを検索する
- 追加のリポジトリを登録していない場合、または指定したリポジトリ内にその名前のパッケージが見つからない場合は、PyPI にフォールバックする
- Poetry は適切なパッケージを見つけると、指定したバージョン制約に最もよく一致するパッケージを見つけようとする
Installing dependencies
To install the defined dependencies for your project, just run the install command.
- プロジェクトに定義された依存関係をインストールするには、install コマンドを実行するだけ
poetry install
このコマンドを実行すると、次の 2 つのいずれかが発生する可能性がある
Installing without poetry.lock
If you have never run the command before and there is also no poetry.lock file present, Poetry simply resolves all dependencies listed in your pyproject.toml file and downloads the latest version of their files.
When Poetry has finished installing, it writes all the packages and their exact versions that it downloaded to the poetry.lock file, locking the project to those specific versions. You should commit the poetry.lock file to your project repo so that all people working on the project are locked to the same versions of dependencies (more below).
- これまでにコマンドを実行したことがなく、poetry.lock ファイルも存在しない場合、Poetry は単に pyproject.toml ファイルにリストされているすべての依存関係を解決し、そのファイルの最新バージョンをダウンロードする
- Poetry のインストールが完了すると、ダウンロードしたすべてのパッケージとその正確なバージョンが Poetry.lock ファイルに書き込まれ、プロジェクトがそれらの特定のバージョンにロックされる
- プロジェクトに取り組んでいるすべての人々が同じバージョンの依存関係にロックされるように、poetry.lock ファイルをプロジェクト リポジトリにコミットする必要がある
Installing with poetry.lock
This brings us to the second scenario. If there is already a poetry.lock file as well as a pyproject.toml file when you run poetry install, it means either you ran the install command before, or someone else on the project ran the install command and committed the poetry.lock file to the project (which is good).
- poetryのインストールを実行するときに、pyproject.toml ファイルだけでなくpoetry.lock ファイルもすでに存在する場合、以前にインストール コマンドを実行したか、プロジェクトの他の誰かがインストール コマンドを実行して、poetry.lock ファイルをプロジェクトにコミットしたか を意味する
Either way, running install when a poetry.lock file is present resolves and installs all dependencies that you listed in pyproject.toml, but Poetry uses the exact versions listed in poetry.lock to ensure that the package versions are consistent for everyone working on your project. As a result you will have all dependencies requested by your pyproject.toml file, but they may not all be at the very latest available versions (some dependencies listed in the poetry.lock file may have released newer versions since the file was created). This is by design, it ensures that your project does not break because of unexpected changes in dependencies.
- いずれの場合でも、poetry.lock ファイルが存在するときに install を実行すると、pyproject.toml にリストしたすべての依存関係が解決され、インストールされる
- Poetry は、poetry.lock にリストされている正確なバージョンを使用して、プロジェクトに取り組むすべての利用者にとってパッケージのバージョンが一貫していることを保証する
- その結果、pyproject.toml ファイルによって要求されたすべての依存関係が取得されるが、それらはすべて最新の利用可能なバージョンではない可能性がある (poetry.lock ファイルにリストされている一部の依存関係は、ファイルの作成後に新しいバージョンがリリースされている可能性がある)
- 依存関係の予期せぬ変更によってプロジェクトが中断されないようにするための仕様
Committing your poetry.lock file to version control
As an application developer
Application developers commit poetry.lock to get more reproducible builds.
Committing this file to VC is important because it will cause anyone who sets up the project to use the exact same versions of the dependencies that you are using. Your CI server, production machines, other developers in your team, everything and everyone runs on the same dependencies, which mitigates the potential for bugs affecting only some parts of the deployments. Even if you develop alone, in six months when reinstalling the project you can feel confident the dependencies installed are still working even if your dependencies released many new versions since then. (See note below about using the update command.)
- アプリケーション開発者は、より再現性の高いビルドを取得するために、poeter.lock をコミットする
- このファイルを VC にコミットすると、プロジェクトをセットアップする人が、自分が使用しているのとまったく同じバージョンの依存関係を使用することになる。このファイルを VC にコミットすることは重要
- これにより、CI サーバー、運用マシン、チーム内の他の開発者、すべてが同じ依存関係で実行されるため、デプロイメントの一部のみに影響を与えるバグの可能性が軽減される
- 一人で開発している場合でも、6 か月後にプロジェクトを再インストールすると、依存関係がそれ以降に多くの新しいバージョンをリリースしたとしても、インストールされた依存関係がまだ動作していると確信できる
As a library developer
Library developers have more to consider. Your users are application developers, and your library will run in a Python environment you don’t control.
- ライブラリ開発者はさらに考慮すべきことがある
- ユーザーはアプリケーション開発者であり、ライブラリは制御できない Python 環境で実行される
The application ignores your library’s lock file. It can use whatever dependency version meets the constraints in your pyproject.toml. The application will probably use the latest compatible dependency version. If your library’s poetry.lock falls behind some new dependency version that breaks things for your users, you’re likely to be the last to find out about it.
- アプリケーションはライブラリのロック ファイルを無視する
- pyproject.toml の制約を満たす依存関係のバージョンであればどれでも使用できる
- アプリケーションはおそらく、互換性のある最新の依存関係バージョンを使用することになる
- あなたのライブラリのpoetry.lockが、ユーザーにとって問題となる新しい依存関係のバージョンよりも遅れている場合、それを知るのはおそらく最後になる
A simple way to avoid such a scenario is to omit the poetry.lock file. However, by doing so, you sacrifice reproducibility and performance to a certain extent. Without a lockfile, it can be difficult to find the reason for failing tests, because in addition to obvious code changes an unnoticed library update might be the culprit. Further, Poetry will have to lock before installing a dependency if poetry.lock has been omitted. Depending on the number of dependencies, locking may take a significant amount of time.
- このようなシナリオを回避する簡単な方法は、poetry.lock ファイルを省略すること
- ただし、これを行うと、再現性とパフォーマンスがある程度犠牲になる
- ロックファイルがないと、明らかなコードの変更に加えて、気付かないライブラリの更新が原因である可能性があるため、テストが失敗する理由を見つけるのが困難になる可能性がある
- さらに、poetry.lock が省略されている場合、依存関係をインストールする前に Poetry をロックする必要がある
- 依存関係の数によっては、ロックにかなりの時間がかかる場合がある
If you do not want to give up the reproducibility and performance benefits, consider a regular refresh of poetry.lock to stay up-to-date and reduce the risk of sudden breakage for users.
- 再現性とパフォーマンスの利点を放棄したくない場合は、poetry.lock を定期的に更新して最新の状態に保ち、ユーザーが突然破損するリスクを軽減することを検討する
Installing dependencies only
The current project is installed in editable mode by default.
If you want to install the dependencies only, run the install command with the --no-root flag:
- 現在のプロジェクトは、デフォルトでは編集可能モードでインストールされる
- 依存関係のみをインストールする場合は、 --no-root フラグを指定して install コマンドを実行する
poetry install --no-root
Updating dependencies to their latest versions
As mentioned above, the poetry.lock file prevents you from automatically getting the latest versions of your dependencies. To update to the latest versions, use the update command. This will fetch the latest matching versions (according to your pyproject.toml file) and update the lock file with the new versions. (This is equivalent to deleting the poetry.lock file and running install again.)
- 上記にあげたとおり、poetry.lock ファイルにより、依存関係の最新バージョンを自動的に取得できなくなる
- 最新バージョンに更新するには、update コマンドを使用する
- これにより、一致する最新のバージョン (pyproject.toml ファイルに従って) がフェッチされ、ロック ファイルが新しいバージョンで更新される
- これは、poetry.lock ファイルを削除して、インストールを再度実行することと同じ
実践
前提
今回、下記の環境で試しています。
- MacOS
- pyenv(任意)
- VSCode(任意)
環境構築
事前準備
- Python 3.12をインストールします
% pyenv install 3.12.5
- ダウンロードを確認します
% pyenv versions * system (set by /Users/XXXX/.pyenv/version) 3.11.5 3.11.9 3.11.9/envs/myenv 3.12.5 myenv --> /Users/XXXX/.pyenv/versions/3.11.9/envs/myenv %
- バージョンを切り替えます。切り替わりました
% pyenv global 3.12.5 % pyenv versions system 3.11.5 3.11.9 3.11.9/envs/myenv * 3.12.5 (set by /Users/XXXX/.pyenv/version) myenv --> /Users/XXXX/.pyenv/versions/3.11.9/envs/myenv % % python --version Python 3.12.5 %
- 仮想環境を作成します
% pyenv virtualenv 3.12.5 testenv
- 作成した仮想環境をアクティブ化します
% pyenv activate testenv (testenv) %
Installation
下記を元に試します。
With the official installerを使用しています。この他のインストール方法を利用する場合は、ドキュメントをご確認ください。
Install Poetry
-
インストーラーをダウンロードし、実行します
% curl -sSL https://install.python-poetry.org | python3 - Retrieving Poetry metadata # Welcome to Poetry! This will download and install the latest version of Poetry, a dependency and package manager for Python. It will add the `poetry` command to Poetry's bin directory, located at: /Users/XXXX/.local/bin You can uninstall at any time by executing this script with the --uninstall option, and these changes will be reverted. Installing Poetry (1.8.3): Done Poetry (1.8.3) is installed now. Great! To get started you need Poetry's bin directory (/Users/XXXX/.local/bin) in your `PATH` environment variable. Add `export PATH="/Users/XXXX/.local/bin:$PATH"` to your shell configuration file. Alternatively, you can call Poetry explicitly with `/Users/XXXX/.local/bin/poetry`. You can test that everything is set up by executing: `poetry --version` %
Add Poetry to your PATH
- パスを通すため、.zshrcに環境変数を設定します
% tail -1 ~/.zshrc export PATH="/Users/XXXX/.local/bin:$PATH" %
- パスが通ったか確認します。(バージョンを確認します)
% source ~/.zshrc % poetry --version Poetry (version 1.8.3) %
1. Pythonパッケージの作成(Poetryを使用)
新しいプロジェクトの作成
- Poetryを使用して、新しいPythonプロジェクトを作成します
% poetry new poetry_package Created package poetry_package in poetry_package %
- 下記のディレクトリ構成が自動的に作成されました
% tree poetry_package poetry_package ├── README.md ├── poetry_package │ └── __init__.py ├── pyproject.toml └── tests └── __init__.py 3 directories, 4 files %
コードの実装
-
poetry_package/module.py
ファイルを作成し、関数を追加しますdef greet(name): return f'Hello, {name}!'
-
poetry_package/__init__.py
を修正し、モジュールをエクスポートします。これにより、モジュール名でインポートできますfrom .module import greet
依存関係の管理
-
依存関係を追加します(requestsライブラリを追加します)
% poetry add requests Using version ^2.32.3 for requests Updating dependencies Resolving dependencies... (0.5s) Package operations: 5 installs, 0 updates, 0 removals - Installing certifi (2024.8.30) - Installing charset-normalizer (3.3.2) - Installing idna (3.10) - Installing urllib3 (2.2.3) - Installing requests (2.32.3) Writing lock file %
-
上記により、requestsライブラリが追加されます。※ dependenciesに追加されています
% cat pyproject.toml [tool.poetry] name = "poetry-package" version = "0.1.0" description = "" authors = ["XXXXXXXX"] readme = "README.md" [tool.poetry.dependencies] python = "^3.12" requests = "^2.32.3" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" %
-
また、
poetry.locl
ファイルでバージョンが固定されます・・・ [[package]] name = "requests" version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" ・・・
-
poetry build
を実行し、パッケージを生成します% poetry build Building poetry-package (0.1.0) - Building sdist - Built poetry_package-0.1.0.tar.gz - Building wheel - Built poetry_package-0.1.0-py3-none-any.whl %
-
distディレクトリが作成され、その配下に、
tar.gz
と、.whl
ファイルが生成されましたpoetry_package % tree . . ├── README.md ├── __init__.py ├── dist │ ├── poetry_package-0.1.0-py3-none-any.whl │ └── poetry_package-0.1.0.tar.gz ├── module.py ├── poetry.lock ├── poetry_package │ └── __init__.py ├── pyproject.toml └── tests └── __init__.py 4 directories, 9 files %
2. GitHubリポジトリへの公開
- GitHubにサインインします
- リポジトリを作成します
- 作成したパッケージディレクトリをPushします
git init git add . git commit -m "Initial commit" git remote add origin https://github.com/yourusername/my_package.git git push -u origin main
3. パッケージのインストール
-
pip
でGitHubリポジトリからインストールします% (testenv) pip install git+https://github.com/XXXXX/poetry_package.git ・・・・ Successfully built poetry-package Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests, poetry-package Successfully installed certifi-2024.8.30 charset-normalizer-3.3.2 idna-3.10 poetry-package-0.1.0 requests-2.32.3 urllib3-2.2.3 %
4. パッケージのインポート
- フォルダを作成します
mkdir poetry_package_use
-
main.py
ファイルを作成し、下記のコードを書きます# main.py from poetry_package import greet print(greet("Taro"))
- 実行します
(testenv) % python main.py poetry_package has been imported Hello, Taro! (testenv) %
考察
今回は、Poetryの基礎的な知識の整理と、実際にパッケージを作成しそれを利用するまで試してみました。
次回以降は、tomlファイルの各セクションの理解をしたいと思います。
参考