LoginSignup
1
1

Pythonソースコードをパッケージ化する方法(他環境へ配布を目的として)(Poetry利用)

Posted at

概要

作成したPythonソースコードを他の環境に持って行って実行する、と言う観点でPythonでのパッケージ化の手順を説明する。

ローカルでの配布を想定し、The Python Package Index (PyPI)への登録などは論じない。

作成する配布用ファイルはWheel形式とし、作成方法は「poetryコマンドを用いる方法」を採用する。

setup.pyを用いる方法(setup()を用いる方法)」との対比を意識して説明する。そのため本記事内には、対比先の記事と同一の説明を含む(扱いがsetup()を用いる場合と同一の個所について)。

目的

Node.jsで言うところの「npm --save install [モジュール名]コマンドで package.json に構築しておけばOK」をPythonでどうやるのか? という疑問への回答を目的とする。

なお、上記に対してそのまま答えるのであれば「Pythonでは、poetryコマンドで依存関係を管理する場合は、poetry newで生成されるpyproject.tomlを一緒に添えておけばよい(受け取った側は poetry installする)」となる。
しかし本記事では、「Pythonでは、パッケージ形式(Wheel形式)に固めて配布し、それをインストールしてパッケージ呼び出し形式で使ってもらう」というケースへの対応を意図する。これは、Pythonの場合はこのケースへの要求が多い、ように感じられたためだ。

想定読者

  • はじめてPythonに触れる人で、しかし他の言語でのプログラミング経験は有する方
    • Python特有の部分はともかく、とりあえずHello World的な出力は悩まずにPythonでコーディングできる方
  • 自身が作成したPythonソースコードで必要な依存関係を、配布時にどう設定すればよいか?に迷っている方

動作環境(検証環境)

次の2つの環境で、サンプルコードの動作確認を実施済み。

  • Windows 10
    • Python 3.11.5
  • WSL2::Ubuntu 22.04.1 LTS
    • dockerイメージ「python:3.9-alpine3.18」

なお、「Python仮想環境」(以下、「仮想環境」と略記)を次のように使い分けるので、明示的に記載するようにする(poetryの仮想環境に集約すべきかもしれないが、パッケージ利用環境ではpoetry利用を強制したくない、ので)。

  • パッケージの開発場面(動作確認とビルド等)はpoetryの仮想環境を利用
  • ビルド済みのパッケージをインストールして動作確認&利用する場面は、Python標準のvenvの仮想環境を利用

※「Python仮想環境とはなんぞや?」と言う方は、付録章の「仮想環境とは?」を参照のこと。

何れの環境でも、poetryパッケージをpip install poetryコマンドで、仮想環境にではなく素のPython環境側にインストールしてあるものとする。また、インストール後に以下の設定を実行済みとする(Poetryの仮想環境の作成場所をプロジェクト直下とするオプション設定)。

poetry config virtualenvs.in-project true

サンプルコード

以下を参照のこと。

パッケージ化対象のサンプルコードの仕様

本記事では、動作に追加パッケージを必要とするケースとして、次の仕様のサンプルコードを用いる。

  • パッケージの本体はweaherforecastフォルダー
    • フォルダー内のPythonファイルopen_meteo_forecast_api.pyにて、「Open-Meteo」が提供するWeb APIを利用して指定地点の向こう1週間の1h毎の予想気温を取得する関数「get()」を提供する
  • 依存関係としてパッケージ「requests」を必要とする
  • 次のようなファイル/フォルダー構造を持つものとする
+-- pyproject.toml
|   
\---weatherforecast/
    +-- open_meteo_forecast_api.py
    +-- __init__.py
    +-- __main__.py        

上記のコードの動作に必要な依存関係(追加パッケージ)をインストールするには次のようにする1

poetry shell
poetry add requests

1つ目のコマンドでPoetryの仮想環境に入り、Poetryの依存関係管理を用いて仮想環境にrequstsパッケージをインストールする。
なお、サンプルコードを用いて上記を実行すると、「既に依存関係として追加されている」と言う以下のメッセージが表示される。

The following packages are already present in the pyproject.toml and will be skipped:
  • requests

この場合は、続いて以下のコマンド用いる(未追加の場合は、追加のタイミングでインストールも走るので不要)。

poetry install

Poetryの仮想環境に入ったり出たりする方法は、付録章の「仮想環境とは?」を参照のこと。

サンプルコードの動作確認

このサンプルコードの動作確認は、以下のコマンドで実施できる。ここで、上述のpoetry shellは実行済みであり、Poetryの仮想環境に入っているものとする。
(このコマンドは、サンプルコードのルートから見て、パッケージweatherforecastを実行している。したがって package直下の__main__.pyが実行される。このフォルダー構造としている理由は、付録章の「ファイル構造に関する補足」を参照のこと)

python -m weatherforecast

上記を実行すると、東京の向こう1週間の1h毎の予想気温が出力される。

パッケージファイル(Wheel形式)の作成方法

pyproject.tomlに必要情報を記載して、poetry buildコマンドを用いて、Wheel形式のパッケージを作成する。本節のコマンドは、素のPython上でもPoetryの仮想環境のどちらで実行しても良い。

pyproject.tomlは例えば、次のように記載する。

[tool.poetry]
name = "weatherforecast"
version = "0.1.0"
description = "sample packages by poetry-toml"
authors = ["Your Name <you@example.com>"]
readme = "README.md"

[tool.poetry.dependencies]
python = ">=3.9,<3.13"
requests = "^2.31.0"


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

このファイルは、ゼロから作成しても良いが、
poetry new [projectname] --name [packagename]コマンド2を実行すると
次のようなpyproject.tomlファイルを含んだpoetry標準構成が出力されるので、
こちらの雛型をベースに必要事項を修正、追記するのが楽である3

[projectname]/
+-- pyproject.toml
+-- README.md
│  
├── tests/
│   +-- __init__.py
│      
└── [packagename]/
    +--  __init__.py

ここで、パッケージの動作に必要な依存関係は、poetry addコマンドを用いて次のように設定する。

poetry add requests [other-package-name]

すると、poetryがpyproject.toml[tool.poetry.dependencies]セクションに適切に追記してくれる。

なお、poetry newコマンドを用いて作成したひな形では(環境によるが)次のように初期設定されており、この状態だとpoetry addコマンドでの任意のパッケージ追加時に「対象のパッケージのPythonバージョン条件(3.11以上、4.00未満)を満たすパッケージが見当たらない」と言うエラーになることがある。

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

その場合は、たとえば次のようにPythonバージョンの条件を狭めるように記載を変更してから、poetry addコマンドを実行すると良い。

[tool.poetry.dependencies]
python = ">=3.9,<3.13"

もしくは、依存関係として必要なパッケージ一覧を記載したファイルrequirements.txtがすでに存在している場合は、そちらに基づいてコマンドpoetry add $(cat requirements.txt)で追加することもできる。

上記のフォルダー構成を作成したら、パッケージフォルダー./[packagename]/へPythonファイル(Pythonモジュール)を格納する。pyproject.tomlを上述のように作成した後、pyproject.tomlファイルのあるフォルダーで、おもむろに次のコマンドを実行する。

poetry build

pyproject.tomlファイルの記述に従い、(nameキーに指定されたフォルダーを対象パッケージとして)パッケージが作成される。

以上で、パッケージ作成は完了。

作成したパッケージの動作確認の方法

Poetryの仮想環境に入っている場合は、いったん仮想環境を抜ける(deactivateコマンド)。

適当な任意のフォルダーに移動し、そこに真っ新な仮想環境を作成する。
たとえば、次のようにする(ここではPython標準のvenv仮想環境を用いるものとする)。

/home/work/downloads # python -m venv .venv_dl
/home/work/downloads # source  .venv_dl/bin/activate

作成したPython仮想環境に入っているパッケージを確認すると、次のようになっている。

(.venv_dl) /home/work/downloads # pip list
---------- -------
pip        23.0.1
setuptools 58.1.0

この環境に対して、先ほど作成したWheelファイル(*.whl)をpipコマンドでインストールする。

(.venv_dl) /home/work/downloads # pip install ./dist/weatherforecast-0.0.1-py3-none-any.whl
Processing /home/work/dist/weatherforecast-0.0.1-py3-none-any.whl
Collecting requests<3.0.0,>=2.31.0
  Using cached requests-2.31.0-py3-none-any.whl (62 kB)
(略)

インストールが完了後の、状態を確認すると次のようになる。

# pip list
Package            Version
------------------ ---------
certifi            2023.7.22
charset-normalizer 3.3.0
idna               3.4
pip                23.0.1
requests           2.31.0
setuptools         58.1.0
urllib3            2.0.6
weatherforecast    0.1.0

インストールしたパッケージを実行するには次のようにする。

python -m weatherforecast

この実行コマンドは「§ サンプルコードの動作確認」で説明したものと同じであり、実行結果も同じとなる。

以上ー。

(付録)

仮想環境とは?

仮想環境とは、「開発環境毎に依存関係を閉じ込める機能」とでも言うべきもの。

たとえばNode.jsであれば「npm install [パッケージA]を実行すると、そのパッケージはnpmコマンドを実行したフォルダー配下でのみ有効」であり、別のフォルダーでnpm instal [パッケージ@バージョン]コマンドを実行した場合はそれぞれのフォルダー毎に異なるバージョンのパッケージを利用する事が可能(「ローカルにインストールする」と呼称する。すべてのフォルダーで利用可能にするには「npm instal [パッケージ名] -g」コマンドで明示的に「グローバルにインストールする」必要がある)。しかしPythonでは「ローカルにインストールする」と言う概念はない。代わりに「仮想環境」を作成して入った状態では、pip install [パッケージ名]でインストールしたパッケージは、その「仮想環境」の中でのみ利用可能となる。異なる仮想環境を作ることで、異なるバージョンのパッケージをインストールして利用することが可能となる。

具体的な仮想環境の作成と、その中に入る2種類の手順を次に示す。

Python標準のvenvパッケージ利用の場合

(1つ目のコマンドの2つ目の引数は任意の識別子だが説明は省略)

python -m venv .venv

.venv\Scripts\activate
# ↑Windowsの場合。↓Linuxの場合は↓。
# source .venv/bin/activate

以降のpip installコマンド、Pythonコマンドはいずれも、この「仮想環境」での動作となる。「仮想環境」を一度作成したら、以降はsource .venv\bin\activateコマンドのみで良い。
なお、仮想環境の実態は「python -m venv .venv」を実行したフォルダ配下に作成されるフォルダ「.venv」となる。2回目以降に「仮想環境」に入るには、そのフォルダ「.venv」があるところで実行する。

「仮想環境」を抜けるには次のコマンド用いる(※別の「仮想環境」に入るには、いったん抜けること)。

deactivate

Poetryパッケージ利用の場合

Poetryに対して以下のコマンドを実行済み(Poetryの仮想環境の作成場所をプロジェクト直下とするオプション値)。

poetry config virtualenvs.in-project true

新規に仮想環境を作成するには、次のコマンドを実行する。実行と同時に仮想環境中に入った状態となる。

poetry shell

以降のPythonコマンドは、この「仮想環境」での動作となる。なお、パッケージの追加インストールにはpoetry add [パッケージ名]を用いる。これによりpyproject.tomlファイルにも自動で依存関係が記録される。

「仮想環境」を抜けるには次のコマンド用いる(※別の「仮想環境」に入るには、いったん抜けること)。

deactivate

作成済みの「仮想環境」に、一度抜けた後に改めて入るには次のコマンドを用いる。

source .venv\bin\activate

仮想環境の実態は「poetry shell」を実行したフォルダ配下に作成されるフォルダ「.venv」となる。2回目以降に「仮想環境」に入るには、そのフォルダ「.venv」があるところで実行する。

なお、2回目以降の仮想環境への入り方は、より正確には次のコマンドとなる。ここでpoetry env info --pathが返す値は、上述の.venvへの絶対パスである。なので、フォルダ「.venv」があるところで実行する分には、上記のように直接指定で良い。

`source $(poetry env info --path)/bin/activate`

Poetry仮想環境に関する参考サイト

新しいシェルの作成を避けるには、source {path_to_venv}/bin/activate (Windowsでは source {path_to_venv}\Scripts\activate.bat) コマンドを実行して、手動で仮想環境を起動する方法があります。仮想環境のパスを取得するには、 poetry env info --path コマンドを実行します。

ファイル構造に関する補足

  • Pythonにおいて、「パッケージ」とは「モジュールをまとめて格納したフォルダー」のことを意味する。「モジュール」とは「Pythonファイル(*.py)」を意味する
  • 「パッケージ化する」とは「パッケージ(フォルダー)に格納したモジュール一式を、配布形式にする」と言える
  • したがって上記のように「対象の関数を定義したPythonソースコードを、フォルダー配下に格納した状態」とするのが望ましいようだ
  1. Poetry関係しない動作確認だけが目的の場合はpip install requestsでも良いのだが、今回はpoetryでの動作確認が目的なので、このようにする。

  2. 「このコマンドは、ほとんどのプロジェクトに適するディレクトリ構造を作成して、新しいPythonプロジェクトに勢いをつける助けをしてくれます」, https://cocoatomo.github.io/poetry-ja/cli/#new

  3. 既存のPythonソースコードに対してパッケージの設定を行う際には、poetry initコマンドを用いる方法もある。 , https://cocoatomo.github.io/poetry-ja/cli/#init

1
1
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
1
1