Pythonコードをインストール可能にする#

以前取り上げたレッスン

前のレッスンで 、Pythonパッケージとは何かについて学びました。また、 Pythonパッケージを作成する利点 についても学びました。

パッケージングチュートリアルシリーズの次のステップは、ローカルでも GitHub (または GitLab) などのウェブサイトからリモートでもインストール可能な Python パッケージを作成することです。このレッスンで作成するパッケージは、Python環境にインストールするために必要な最低限の要素しか持っていません。

あなたのコードをインストール可能にすることは、PyPIから直接インストール可能な完全なPythonパッケージを作成するための重要なステップです。

インストール可能なパッケージを作成する基本的な手順を示した図です。 右を向いた矢印の箱が4つあります。 ボックスは、あなたのコード、パッケージ構造の作成、pyproject.tomlへのメタデータの追加、およびpip installパッケージを読み込みます。

基本的なインストール可能パッケージには、以下のものが必要です: コード、 特定のパッケージファイル構造 、パッケージの名前とバージョンを含む pyproject.toml が必要です。これらのアイテムが正しいディレクトリ構造になっていれば、pipであなたのコンピュータのどの環境にもパッケージをインストールすることができます。このレッスンでは、基本的なインストール可能パッケージの作成方法を学びます。#

このレッスンについて

このレッスンで学ぶこと:

  • ローカルとGitHubの両方で、あなたのコードをあらゆるPython環境にインストール可能にする方法

  • パッケージの依存関係とメタデータを含む基本的な pyproject.toml ファイルの作成方法。このファイルは、パッケージをインストール可能にするために必要です。

  • パッケージの ビルド とインストールに使用する ビルドバックエンド を宣言する方法

  • インタラクティブな開発のために編集可能モードでパッケージをインストールする方法

このレッスンを完了するために必要なもの

このレッスンを完了するには、あなたのコンピュータにローカルのPython環境とシェルが必要です。 Hatchのインストール も必要です。

Windowsを使用している、またはシェルに精通していない場合は、Carpentriesのシェルレッスン[1] をチェックアウトすることをお勧めします。 Windowsユーザーは、Shellやgitに関連するステップのためにツールを設定する必要があるでしょう。

次に来るもの

これからのレッスンでは、その方法を学びます:

  • PyPIへのパッケージの公開

  • コミュニティの利用をサポートするために、パッケージに README ファイルを追加してください。

  • PyPI公開をサポートするために、パッケージにプロジェクトのメタデータを追加します

この図には2つの小さなボックスがあり、右側にPython環境を示す矢印があります。 小さなボックスには、your-packageとpip install packageと書かれています。 右側の環境欄には「あなたのPython環境」と書かれています。 Matplotlib、NumPy、Pandas、Xarray、GeoPandasなどのコアパッケージとともに、your-packageがリストアップされています。

あなたのコードをインストール可能にすることは、公開可能なPythonパッケージを作成するための最初のステップです。 あなたのコードがインストール可能になると、それはPythonパッケージとなり、あなたのコンピュータ上の任意のPython環境に追加し、PandasやGeoPandasなどのパッケージをインポートするのと同じ方法でインポートすることができます。あなたのコードがGitHubやGitLabにあるなら、そこから直接インストールすることもできます。#

Pythonパッケージのディレクトリ構造について#

Pythonコードをインストール可能にするには、以下の要素を含む特定のディレクトリ構造を作成する必要があります:

  • pyproject.toml ファイル。

  • 特定のディレクトリ構造。

  • いくつかのコード。

  • コードディレクトリの __init__.py ファイル。

このレッスンで作成するディレクトリ構造は次のようになります:

pyospackage/  # Your project directory
 └─ pyproject.toml
 └─ src/  # The source (src) directory ensures your tests always run on the installed version of your code
    └── pyospackage/  # Package directory where code lives
        ├── __init__.py
        ├── add_numbers.py
        └── # Add any other .py modules that you want here

基本パッケージのディレクトリ構造について#

上記のレイアウトについて、いくつかの点に注目してください:

  1. パッケージのコードは src/packagename ディレクトリにある。インストールされたバージョンのコードでテストを実行していることを確認するため、 srcsource code の略)ディレクトリを使用することをお勧めします。

  2. src ディレクトリの中に pyospackage というパッケージディレクトリがあります。 ディレクトリ名にはパッケージ名を使用します。 これは、インストール後にPythonコードでパッケージをインポートする際の名前になります。

  3. パッケージディレクトリには __init__.py ファイルと Python モジュールがあります。以下に __init__.py ファイルについて詳しく説明します。

  4. pyproject.toml ファイルはパッケージのルートディレクトリにあります。

  5. パッケージのルートディレクトリの名前は、パッケージ名である pyospackage です。これは必須ではありませんが、GitHub / GitLabのリポジトリ名とルートディレクトリ名がパッケージ名と同じであることをよく見かけます。

__init__.py ファイルとは何ですか?#

__init__.py ファイルは Python にディレクトリを Python パッケージとして扱うように指示します。 このように、__init__.py ファイルがあるディレクトリは Python に直接インポートすることができます。 Python に認識させるために __init__.py ファイルにコードを記述する必要はありません; 空であることもあります。

例えば、 __init__.py ファイルを持つ上記のファイル構造の例に従って、次のように実行します:

import pyospackage

pyproject.tomlファイルとは何ですか?#

pyproject.toml ファイルは:

  • プロジェクトのメタデータ (名前、作者、ライセンスなど) を定義します。

  • 依存関係 (依存するパッケージ) を定義します。

  • パッケージのビルド に使用するビルドバックエンドを指定し、設定します。

__init__.pypyproject.toml ファイルが追加されたら、pipなどのツールを使ってパッケージをビルドし、インストール可能なPythonパッケージとして配布することができます。 pyproject.toml ファイルには、パッケージをインストールするために、以下のようないくつかの基本的な項目が定義されている必要があることに注意してください:

  • 使用したい build-backend を指定します、

  • プロジェクトの nameversion を指定する。

pyproject.tomlファイルが重要な理由

pyproject.toml ファイルは setup.py ファイルと setup.cfg ファイルの機能の一部を置き換えます。 pyproject.toml がないパッケージをpipインストールしようとすると、以下のエラーが発生します:

GitHub/pyospackage/testme
➜ python -m pip install .
ERROR: Directory '.' is not installable.
Neither 'setup.py' nor 'pyproject.toml' found.

setup.py についてのメモ

プロジェクトが既に setup.py ファイルを定義している場合、ハッチを使用して自動的に pyproject.toml を作成することができます。

Pythonパッケージを作成しましょう!#

Python パッケージのディレクトリ構造の基本を理解し、関連するキーファイル (__init__.pypyproject.toml) を理解したところで、いよいよ Python パッケージを作成します! 以下では、Hatchを使って、上で説明したようなディレクトリ構造を作成します。

ステップ1: パッケージのディレクトリ構造を設定する#

  • シェルまたはお好みのターミナルを開きます。

  • シェルで cd コマンドを使い、パッケージのディレクトリを置く場所に移動します。 Hatchがパッケージディレクトリを作成してくれます。

  • パッケージの名前を決めてください。 名前は以下のようにします:

    • スペースがない (必須)

    • すべて小文字を使用 (推奨)。 このチュートリアルでは pyospackage を使用します。

    • 名前にはアルファベットと _ または - のみを使用してください。これは、pyos*packageという名前は使えないことを意味します。しかし、 pyos_package または pyos-package という名前であれば、どちらでも構いません。

Hatchとプロジェクト名

hatch new を実行したとき、 Hatch は、あなたのプロジェクトの名前を決定します。

これには以下のようなものがあります:

  • 最上位ディレクトリのダッシュ記号

  • pyproject.tomlのプロジェクト名をダッシュで囲みます

  • パッケージディレクトリ名のアンダースコア

 hatch new pyos-package
pyos-package
├── src
│   └── pyos_package
│       ├── __about__.py
│       └── __init__.py
├── LICENSE.txt
├── README.md
└── pyproject.toml

アンダースコア付きの名前を使っても、Hatchは同じものを返します:

 hatch new pyos_package
pyos-package
├── src
│   └── pyos_package
│       ├── __about__.py
│       └── __init__.py
├── LICENSE.txt
├── README.md
└── pyproject.toml

上記のどちらの例でも、hatchが作成するpyproject.tomlファイルのプロジェクト名は pyos-package です。

次に実行するのは:

➜ hatch new pyospackage
pyospackage
├── src
│   └── pyospackage
│       ├── __about__.py
│       └── __init__.py
├── LICENSE.txt
├── README.md
└── pyproject.toml

最終的なプロジェクトのディレクトリ構造は以下のようになるはずです:

pyospackage # This is your project directory
├── src
│   └── pyospackage # This is your package directory where your code lives       ├── __about__.py
│       └── __init__.py
├── LICENSE.txt
├── README.md
└── pyproject.toml # this file contains package metadata

ステップ 2: パッケージにモジュールを追加する#

Python モジュールとは、パッケージにアクセスさせ、実行させたいコードを含む .py ファイルを指します。 pyospackage サブディレクトリに、少なくとも1つのPythonモジュール (.py ファイル) を追加します。

もしまだコードを持っておらず、Python パッケージの作成方法を学んでいるところなら、空の add_numbers.py ファイルを作成してください。 この add_numbers.py ファイルに以下に示すコードを入力します。

Pythonモジュールと __init__.py ファイル

モジュールという言葉を目にしたとき、私たちはPythonのコードを含む .py ファイルを指しています。

__init__.py は、Pythonがディレクトリに少なくとも1つのモジュールが含まれていることを認識できるようにします。 パッケージは複数のモジュール [2] を持つことができます。

プロジェクトディレクトリはこのようになっているはずです:

pyospackage/
└─ pyproject.toml
└─ src/
   └── pyospackage/
       ├── __init__.py
       ├── add_numbers.py

ステップ3: モジュールにコードを追加する#

Python のパッケージをゼロから作るのであれば、以下のコードを add_numbers.py モジュールに追加してください。 以下の関数は2つの整数を加算して結果を返します。以下のコードには、今後のチュートリアルで確認するいくつかの機能があることに注目してください:

  1. これは numpyスタイルのdocstring を持っています。

  2. typing を使用します。

Pythonは、使いたいドキュメントのビルドシステムに応じて、多くの異なるdocstringsフォーマットをサポートすることができます。 Pythonオブジェクトを文書化するために最もよくサポートされている形式は、NumPy Style Docstring[3]、Google Style Docstring[4]、Epytext Style Docstring[5]です。

pyOpenSciは、NumPyのDocstring規約を使用することを推奨します。

もしあなたがまだdocstringsやタイピングに慣れていなくても大丈夫です。 両方のトピックの概要については、 pyOpenSciパッケージングガイドのこのページ を参照してください。

def add_num(a: int, b: int) -> int:
    """
    Add two numbers.

    Parameters
    ----------
    a : int
        The first number to be added.
    b : int
        The second number to be added.

    Returns
    -------
    int
        The sum of the two input numbers (a + b).

    Examples
    --------
    >>> add_num(3, 5)
    8
    >>> add_num(-2, 7)
    5
    """
    return a + b

ステップ 4: pyproject.toml ファイルのメタデータを修正する#

次に、Hatchが pyproject.toml ファイルに追加するメタデータ (情報) の一部を変更します。私たちの example pyospackage GitHubリポジトリ にあるファイルをコピーしてください。

TOMLファイルの概要

TOMLフォーマット は表と変数で構成されます。 表は角括弧で示される情報のセクションです:

[this-is-a-table].

テーブルには、変数名と = 記号で定義された変数を入れることができます。 例えば、build-system テーブルは以下の2(つの)変数を保持することが多いです:

  1. requires= は、ビルドツールに対して、パッケージをビルドする前にインス トールする必要があるツールを指示します。 この場合 hatchling

  2. build-backend = 、これは、特定のビルドバックエンド名を定義するために使われます、(この例では、 hatchling.build を使用しています)。

# An example of the build-system table which contains two variables - requires and build-backend
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

TOMLはデータ構造を整理し、設定ファイル内の関係を定義します。

pyproject.tomlフォーマットの詳細はこちら。

pyproject.toml フォーマットについては、 このファイルにメタデータや情報を追加する次のレッスン で詳しく学びます。

  • Hatchが作成した pyproject.toml ファイルをお好みのテキストエディタで開いてください。 下の例のようになるはずです。

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pyospackage"
dynamic = ["version"]
description = ''
readme = "README.md"
requires-python = ">=3.8"
license = "MIT"
keywords = []
authors = [
  { name = "Leah Wasser", email = "leah@pyopensci.org" },
]
classifiers = [
  "Development Status :: 4 - Beta",
  "Programming Language :: Python",
  "Programming Language :: Python :: 3.8",
  "Programming Language :: Python :: 3.9",
  "Programming Language :: Python :: 3.10",
  "Programming Language :: Python :: 3.11",
  "Programming Language :: Python :: 3.12",
  "Programming Language :: Python :: Implementation :: CPython",
  "Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = []

[project.urls]
Documentation = "https://github.com/unknown/pyospackage#readme"
Issues = "https://github.com/unknown/pyospackage/issues"
Source = "https://github.com/unknown/pyospackage"

[tool.hatch.version]
path = "src/pyospackage/__about__.py"

以下のようにファイルを編集します:

  1. dynamic = ["version"] を削除する: これは、git のコミット履歴に保存されているタグに基づいて、動的なバージョン管理を設定します。後のレッスンでこの実装方法を説明します。

  2. 先ほど削除した dynamic = ["version"] の場所に version = "0.1" を追加します。これで手動バージョン管理が設定されます。

  3. 説明文がなければ記入してください。

[project]
name = "pyospackage"
# dynamic = ["version"] <- replace this...
version = "0.1" # with this
description = 'A simple Python package that adds numbers together' # Add a description of your package if that is not already populated
  1. ファイルの一番下にある [tool.hatch.version] テーブルを削除します。

[tool.hatch.version]
path = "src/pyospackage/__about__.py"

オプション: プロジェクトの分類子を調整する#

Hatchはデフォルトで、パッケージがサポートするPythonのバージョンを定義する分類子のリストを提供します。これらの分類子はパッケージのビルドには一切影響を与えず、主にパッケージをPyPIに公開するときに使用することを目的としています。

PyPIに公開する予定がなければ、このセクションは飛ばして構いません。しかし、もし望むなら、少しきれいにすることもできます。

はじめに:

  • Python 3.8のサポートを削除

  • [project] テーブル内で、 requires-python = ">3.8"requires-python = ">3.9" に更新します。

このレッスンでは純粋な Python パッケージを作成するので、以下の分類子は削除してかまいません:

classifiers = [
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]

新しいpyproject.tomlファイルは次のようになるはずです:

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pyospackage"
version = "0.1"
description = 'A python package that adds numbers together.'
readme = "README.md"
requires-python = ">=3.9"
license = "MIT"
keywords = []
authors = [
  { name = "FirstName LastName", email = "youremail@youremail.org" },
]
classifiers = [
  "Development Status :: 4 - Beta",
  "Programming Language :: Python",
  "Programming Language :: Python :: 3.9",
  "Programming Language :: Python :: 3.10",
  "Programming Language :: Python :: 3.11",
  "Programming Language :: Python :: 3.12",
]
dependencies = []

[project.urls]
Documentation = "https://github.com/unknown/pyospackage#readme"
Issues = "https://github.com/unknown/pyospackage/issues"
Source = "https://github.com/unknown/pyospackage"

pyproject.tomlファイルに最低限必要なもの

PyPIで公開するために pyproject.toml ファイルに必要な情報は、 パッケージ名バージョン です。 しかし、 pyproject.toml ファイルの早い段階でメタデータを具体化することをお勧めします。

一度pyproject.tomlファイルにプロジェクトのメタデータがあれば、それを更新することはほとんどありません。次のレッスンでは、このファイルにさらにメタデータと構造を追加します。

ステップ 5: パッケージをローカルにインストールする#

この時点であなたは以下を持っているはずです:

  1. pyproject.toml ファイルをルートに持つプロジェクトのディレクトリ構造

  2. 空の __init__.py ファイルを含むパッケージ・ディレクトリと

  3. 少なくとも1つのPythonモジュール (e.g. add_numbers.py)

これで Python パッケージをインストール(ビルド)する準備ができました!

hatchを使ってもできますが、このレッスンではpipを使います、そうすれば、あなたの好みの環境にツールをインストールする方法を見ることができます。

  • まず、お好みのシェルを開き (Windowsユーザーはgitbashのようなものを使っているかもしれません) 、まだプロジェクトディレクトリにいなければ、 cd してください。

  • 使用したいPython環境をアクティブにします。

  • python -m pip install -e . を実行します。

# Activate your environment using conda or venv
# Below we use conda but you can do the same thing with venv!
> conda activate pyosdev
(pyosdev)
> conda info
    active environment : pyosdev
    active env location : /Users/your-path/mambaforge/envs/pyosdev
# Cd into your project directory
> cd pyospackage
# Install your package
> python -m pip install -e .

Obtaining file:///Users/leahawasser/Documents/GitHub/pyos/pyosPackage
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done

# Check to see if the package is installed
> conda list
# use pip list instead of conda list here if you are working in an venv environment rather than a conda envt

python -m pip install -e . は何をしているのか?

python -m pip install -e . を分解してみましょう

python -m pip install -e . は、 編集可能モード (-e) で、現在のアクティブな Python 環境にパッケージをインストールします。 編集可能モードでパッケージをインストールすることで、あなたのコードで作業し、お気に入りのPythonインターフェースでインタラクティブに更新をテストすることができます。 編集可能モードの重要な注意点のひとつは、コードを更新するたびに、そのコードが更新されるということです、 その場合、Pythonを再起動する必要があるかもしれません。

(編集可能モードではなく) 定期的にパッケージをインストールしたい場合は、次のようにします:

  • python -m pip install .

pip を呼び出す際に python -m を使用する

上記では、 python -m を使用して、現在アクティブな環境にインストールされている pip のバージョンを呼び出します。 python -m は、現在の環境にインストールされているバージョンの pip を呼び出していることを確認するために重要です。

あなたの環境でpyospackageを探す#

パッケージをインストールしたら、現在の環境でそれを見ることができます。 venv または conda を使用している場合、 pip list で現在インストールされているパッケージを確認することができます。

pyospackageは編集可能モード (-e) でインストールされるため、pipはプロジェクトのコードへのディレクトリパスを表示することに注意してください。

$ pip list

➜ pip list
Package                       Version        Editable project location
----------------------------- -------------- --------------------------------------------------------------
...
arrow                         1.2.3
...
...
mamba                         1.1.0
markdown-it-py                2.2.0
MarkupSafe                    2.1.2
matplotlib                    3.7.1
msgpack                       1.0.5
mypy                          1.4.1
nox                           2021.10.1
numpy                         1.24.2
packaging                     23.0
pandas                        1.5.3
pyosPackage                   0.1            /Users/yourusername/path/here/pyosPackage
...
...
...

ステップ 6: 新しいパッケージをテストする#

パッケージをインストールしたら、選択したターミナルのコマンドプロンプトで "python" と入力し、アクティブなPython環境でPythonセッションを開始します。

これでパッケージをインポートして add_num 関数にアクセスできます。

 python
Python 3.11.4 | packaged by conda-forge
Type "help", "copyright", "credits" or "license" for more information.
>>> from pyospackage.add_numbers import add_num
>>> add_num(1, 2)
3

GitHubからパッケージをインストールする

PyPIに公開せずにコードを共有したい場合は、いつでも構文を使ってGitHubから直接パッケージをインストールできます:

python -m pip install git+https://github.com/user/repo.git@branch_or_tag

GitHubのパッケージをインストール可能にするには、次のようにします:

  1. 新しいGitHubリポジトリを作成する

  2. 上記で作成したプロジェクトディレクトリの内容をGitHubにプッシュします

  3. 最後に、上記のコマンドを使ってGitHubからパッケージをインストールします。 上記のコマンドを使用する際は、user、repo、branch_or_tag を特定の値に置き換えることをお忘れなく。

例えば、以下のようにpyOpenSciリポジトリのmainブランチからpyospackageをインストールします。

python -m pip install git+https://github.com/user/repo.git@branch_or_tag

おめでとうございます! あなたは最初のPythonパッケージを作成しました#

やったね! これでどんなPython環境にもインストールできるPythonパッケージができました。

これからのレッスンではあなたは:

脚注#