科学的PythonプロジェクトのためのPythonパッケージ構造#

Pythonのパッケージングエコシステムでよく見られるレイアウトは2種類あります。: srcとフラットレイアウどちらのレイアウトも、異なるメンテナグループにとって利点があります。

Python パッケージの作成には src/ レイアウト (後述) を使うことを強く推奨しますが、必須ではありません。 このレイアウトは、 PyPA packaging guide tutorial でも推奨されています。

pyOpenSciは査読のために特定のパッケージ構造を要求することはありません

新しいレイアウトに移行することは、既存のメンテナンス担当者にとって重要な労力となることは理解しています。

このページの概要では、これから Python のパッケージングを始める人や、パッケージがシンプルなビルドで、より失敗のないアプローチに移行することに前向きな人に最適だと思われる推奨事項を紹介します。

他のリソースもチェックできます:

Hatch のようなツールを使って、最新の Python パッケージ構造を素早く作成することができます。 クイックスタートチュートリアルをご覧ください:

パッケージを構築するための仕組み作りを学びたいですか? こちらをクリックしてください。

Pythonパッケージのソースレイアウトとは何ですか?#

src/package のレイアウト構造の例を以下に示します。

myPackageRepoName
├── CHANGELOG.md               ┐
├── CODE_OF_CONDUCT.md         │
├── CONTRIBUTING.md            │
├── docs                       │ Package documentation
│   └── index.md
│   └── ...                    │
├── LICENSE                    │
├── README.md                  ┘
├── pyproject.toml             ] Package metadata and build configuration
├── src                        ┐
│   └── myPackage              │
│       ├── __init__.py        │ Package source code
│       ├── moduleA.py         │
│       └── moduleB.py         ┘
└── tests                      ┐
   └── ...                     ┘ Package tests

上の例では、以下のディレクトリの位置に注意してください:

  • docs/: docsの章で説明したように、このディレクトリにはユーザー向けのドキュメントサイトが含まれます。 src/ レイアウトでは、通常 docs/ は src/ フォルダの同じディレクトリレベルに含まれます。

  • tests/ このディレクトリには、プロジェクトコードのテストが含まれます。 src/ レイアウトでは、テストは通常 src/ フォルダの同じディレクトリレベルに含まれます。

  • src/package/: これはPythonプロジェクトのコードを含むディレクトリです。 "Package" は通常プロジェクトの名前です。

また、上記の例では、pyOpenSciが必要とするすべてのコアドキュメントファイルがプロジェクトディレクトリのルートにあることに注意してください。 これらのファイルには以下が含まれています:

  • CHANGELOG.md

  • CODE_OF_CONDUCT.md

  • CONTRIBUTING.md

  • LICENSE.txt

  • README.md

パッケージングに関するドキュメント要件については、こちらをご覧ください。

src/package レイアウトを使用する科学的パッケージの例

src/ のレイアウトとテスト#

src/package レイアウトを使用する利点は、パッケージの作業ディレクトリ内のファイルではなく、インストールされたバージョンのパッケージに対してテストが実行されることを保証することです。 あなたのパッケージのインストールされたバージョンではなく、あなたのファイルでテストを実行すると、あなたのパッケージがインストールされたときにユーザが遭遇する問題を見逃してしまうかもしれません。

tests/src/package ディレクトリの外にある場合、それらはパッケージの wheel には含まれません。これにより、パッケージのサイズがわずかに小さくなり、PyPIにかかるストレージの負担が小さくなり、フェッチが速くなります。

Pythonはどのようにインポートモジュールを検出し、優先順位をつけるか

デフォルトでは、Pythonは現在の作業ディレクトリにあるモジュールをPythonモジュール検索パスの先頭に追加します。

つまり、パッケージの作業ディレクトリでフラットレイアウトの /package/module.py を使ってテストを実行すると、Python はインストールされたパッケージを検出する前に package/module.py ファイルを検出します。

しかし、あなたのパッケージが src/ ディレクトリ構造の src/package にある場合、デフォルトでは Python のパスに追加されません。 これは、あなたのパッケージをインポートするとき、Python は(あなたのパッケージがインストールされている)アクティブな環境を強制的に検索することを意味します。

注意: Pythonのバージョン3.11以上では、インストールされているパッケージを優先的に使うようにパスの設定を調整することができます ( PYTHONSAFEPATH など)。

パッケージホイールにテストを含めない#

パッケージに tests を書くことは重要です、しかし、デフォルトでテストを パッケージホイール の一部として含めることはお勧めしません。しかし、パッケージの配布にテストを含めないと、自分以外の人が自分のシステムでパッケージが正しく機能しているかどうかをテストすることが難しくなります。小さなテストスイート (Python ファイル + データ) を持っていて、ユーザが自分のシステムでローカルにテストを実行したいと思う場合、tests/ ディレクトリを src/package ディレクトリに移動することでテストを含めることができます (以下の例を参照してください)。

src/
  package/
    tests/
docs/

src/package ディレクトリに tests/ ディレクトリをインクルードすることで、パッケージの wheel にテストが含まれるようになります。

パッケージ配布にテストを含める方法については、 pytest documentation for more about including tests in your package distribution を必ず読んでください。

パッケージwheelにテストとデータを含める際の課題

テストは、特にテストデータを伴う場合、以下のような小さな課題を生み出す可能性があります:

  • PyPI上のストレージスペースとして時間の経過とともに蓄積される、ディストリビューション内のスペースを占有します。

  • ファイルサイズが大きいと、パッケージのインストールも遅くなります。

しかし、場合によっては、特に科学的なPythonのエコシステムでは、テストを含める必要があるかもしれません。

テストスイートのデータセットをパッケージに含めないでください#

テストをパッケージ配布に含める場合、テストスイートディレクトリにデータを含めることは強くお勧めしません。 そうではなく、FigshareやZenodoのようなリポジトリでテストデータをホストします。 Pooch のようなツールを使用して、あなた(またはユーザー)がテストを実行する際にデータにアクセスします。

Python パッケージテストの詳細については、 ガイドの tests のセクション を参照してください。

  • src/package レイアウトの方が意味的に明確である。 コードは常に src/package ディレクトリにあり、 tests/docs/ はルートディレクトリにあります。

重要

パッケージのテストにデータが必要な場合は、そのデータをパッケージ構造に含めないでください。 パッケージ構造にデータをインクルードすると、配布ファイルのサイズが大きくなります。 これは PyPI や Anaconda.org のような何千ものパッケージのアップロードに対応しなければならないリポジトリにメンテナンスの負担をかけます。

Pythonパッケージ作成のクイックスタートチュートリアルはこちらです。

フラットなPythonパッケージレイアウトとは何ですか?#

多くの科学的パッケージは flat-layout を使用しています:

  • このレイアウトは、NumPy、SciPy、Matplotlibのような多くの科学的Pythonパッケージで使用されています。

  • 多くのPythonツールは、他の言語のツールや、コンパイルステップを含む複雑なビルドに依存しています。 多くのメンテナーは、より複雑なビルドのためにフラットレイアウトの機能を好みます。

上述した src/package レイアウトを使用することを推奨しますが、特にこのレイアウトを使用するパッケージに貢献する予定がある場合は、フラットレイアウトも理解することが重要です。

ほとんどの科学的Pythonパッケージがソースを使わない理由

ほとんどの場合、すでにフラットレイアウトを使用している大規模な科学パッケージの src/package レイアウトへの移行は、かなりの時間を消費します。

しかし、初心者にとってsrc/packageレイアウトを使う利点は大きいです。そのため、新しいパッケージを作成する場合は、 src/package レイアウトを使用することをお勧めします。

エコシステムの中で数多くのパッケージが src/package レイアウトに移行しなければなりませんでした。

フラットレイアウトの構造はどのようなものですか?#

フラットレイアウトの主な特徴は以下の通りです:

  • パッケージのソースコードは、ディレクトリのルートにあるパッケージ名のディレクトリに格納されます

  • 多くの場合、 tests/ ディレクトリも同じ package ディレクトリの中にあります。

以下に、フラットレイアウトを使った科学的Pythonパッケージの推奨構造を示します。

myPackage/
├── CHANGELOG.md             ┐
├── CODE_OF_CONDUCT.md       │
├── CONTRIBUTING.md          │
├── docs/                     Package documentation
│   └── ...                  │
├── LICENSE                  │
├── README.md                ┘
├── pyproject.toml           ] Package metadata and build configuration
|   myPackage/               ┐
│     ├── __init__.py         Package source code
│     ├── moduleA.py         │
│     └── moduleB.py               tests/                         └── test-file1.py    | Package tests
        └── ....             

Pythonパッケージでフラットレイアウトを使うメリット#

フラットレイアウトを採用することは、科学コミュニティにとってもメリットがあります。

  • この構造は歴史的にエコシステム全体で使われてきたものであり、これを使うパッケージが変わることはないでしょう。

  • ルートディレクトリからパッケージを直接インポートすることができます。これがそれぞれのワークフローに組み込まれている人もいるでしょう。しかし、初心者がこの方法をとる危険性は、インストールされたバージョンのパッケージに対して開発やテストを行っていないことにあります。 むしろ、フラットファイルを直接扱うことになります。

フラットレイアウトを使用する科学的Pythonのコアパッケージ

これらのパッケージをすべて別のレイアウトに移行するのは、かなりのメンテナンスコストと負担になるでしょう。 これらのツールのソースレイアウトの潜在的な利点は、メンテナンスの投資に見合うものではありません。