Python パッケージを作成する

Beginner

This tutorial is from open-source community. Access the source code

はじめに

この実験では、Python パッケージを作成して整理する方法を学びます。Python パッケージは、コードを構造化する優れた方法であり、コードをよりモジュール化、再利用可能、かつ保守可能にします。

この実験の目的は、Python パッケージとは何かを理解し、基本的なパッケージ構造を作成し、関連する Python モジュールをまとまりのあるパッケージに整理し、新しいパッケージ構造で動作するようにインポート文を更新することです。

これは Guided Lab です。学習と実践を支援するためのステップバイステップの指示を提供します。各ステップを完了し、実践的な経験を積むために、指示に注意深く従ってください。過去のデータによると、この 中級 レベルの実験の完了率は 67%です。学習者から 100% の好評価を得ています。

Python パッケージの理解

Python パッケージを作成する前に、Python パッケージとは何かを理解しましょう。Python パッケージは基本的にディレクトリです。このディレクトリの中には、複数の Python モジュールファイル(Python コードを含む .py ファイル)があります。さらに、__init__.py という特別なファイルがあります。このファイルは空でも構いませんが、このファイルが存在することで、そのディレクトリが Python パッケージであることが示されます。この構造の目的は、関連するコードを単一のディレクトリ階層に整理するのを助けることです。

パッケージにはいくつかの利点があります。まず、コードを論理的に構造化することができます。すべての Python ファイルが散らばっているのではなく、関連する機能をパッケージにまとめることができます。次に、モジュール間の名前の衝突を回避するのに役立ちます。パッケージは名前空間を作成するため、異なるパッケージに同じ名前のモジュールを持つことができ、問題は発生しません。最後に、コードのインポートと使用がより便利になります。パッケージ全体またはその中の特定のモジュールを簡単にインポートすることができます。

では、現在のプロジェクトディレクトリにあるファイルを見てみましょう。ファイルを一覧表示するには、ターミナルで次のコマンドを使用します。

ls -l

このコマンドを実行すると、次のようなファイルが表示されるはずです。

portfolio.csv
reader.py
stock.py
structure.py
tableformat.py
validate.py

これらの Python ファイルはすべて関連しており、連携して動作しますが、現在は個別のモジュールに過ぎません。この実験では、これらを structly というまとまりのあるパッケージに整理することを目標としています。

各ファイルの機能を簡単に理解してみましょう。

  • structure.py: このファイルは、基本的な Structure クラスとさまざまなディスクリプタを定義しています。これらのディスクリプタは型検証に使用され、つまり、プログラムで使用されるデータが正しい型であることを確認するのに役立ちます。
  • validate.py: このファイルには、structure モジュールで使用される検証機能が含まれています。これにより、特定のルールに従ってデータを検証することができます。
  • reader.py: このファイルは、CSV データを読み取るための関数を提供します。CSV(Comma-Separated Values)は、表形式のデータを保存するための一般的なファイル形式です。
  • tableformat.py: このファイルには、データを表形式に整形するためのクラスと関数が含まれています。データをより整理された形式で表示したい場合に便利です。
  • stock.py: このファイルは、他のモジュールを使用して Stock クラスを定義し、株式データを処理します。他のモジュールの機能を組み合わせて、株式データに関連する特定のタスクを実行します。

次のステップでは、パッケージ構造を作成します。

パッケージ構造の作成

ここでは、Python パッケージを作成します。まずは、Python パッケージとは何かを理解しましょう。Python パッケージは、関連する Python モジュールを単一のディレクトリ階層に整理する方法です。これにより、コードの管理と再利用がより効果的に行えます。Python パッケージを作成するには、以下の手順に従います。

  1. パッケージ名のディレクトリを作成します。このディレクトリは、パッケージに属するすべてのモジュールのコンテナとなります。
  2. このディレクトリ内に __init__.py ファイルを作成します。このファイルは、Python がディレクトリをパッケージとして認識するために重要です。パッケージをインポートすると、__init__.py 内のコードが実行され、パッケージの初期化に使用できます。
  3. Python モジュールファイルをこのディレクトリに移動します。この手順により、関連するすべてのコードがパッケージ内にまとめられます。

パッケージ構造をステップバイステップで作成しましょう。

  1. まず、structly というディレクトリを作成します。これがパッケージのルートディレクトリになります。
mkdir structly
  1. 次に、structly ディレクトリ内に空の __init__.py ファイルを作成します。
touch structly/__init__.py

__init__.py ファイルは空でも構いませんが、Python がディレクトリをパッケージとして扱うために必要です。パッケージをインポートすると、__init__.py 内のコードが実行され、パッケージの初期化に使用できます。

  1. 次に、Python モジュールファイルを structly ディレクトリに移動します。これらのモジュールファイルには、パッケージに含めたい関数やクラスが含まれています。
mv structure.py validate.py reader.py tableformat.py structly/
  1. すべてのファイルが正しく移動されたことを確認します。ls -l コマンドを使用して、structly ディレクトリの内容を一覧表示できます。
ls -l structly/

以下のようにファイルが表示されるはずです。

__init__.py
reader.py
structure.py
tableformat.py
validate.py

これで、基本的なパッケージ構造が作成されました。ディレクトリ階層は次のようになります。

project/
├── portfolio.csv
├── stock.py
└── structly/
    ├── __init__.py
    ├── reader.py
    ├── structure.py
    ├── tableformat.py
    └── validate.py

次のステップでは、パッケージが正しく動作するようにインポート文を修正します。

インポート文の修正

なぜこれを行う必要があるのかを理解しましょう。ファイルを structly パッケージに移動したことで、Python がモジュールを探す方法が変わりました。各ファイルのインポート文は、新しいパッケージ構造に合わせて更新する必要があります。Python はこれらのインポート文を使用して他のモジュールからコードを見つけて使用するため、これは非常に重要です。

structure.py ファイルの更新は非常に重要です。このファイルは validate.py ファイルから関数やクラスをインポートしています。これらのファイルは両方とも同じ structly パッケージ内にあるため、インポート文をそれに応じて調整する必要があります。

まず、エディタで structly/structure.py ファイルを開きましょう。ファイルエクスプローラーで structly/structure.py をクリックするか、ターミナルで次のコマンドを実行してください。

## ファイルエクスプローラーで structly/structure.py をクリックするか、以下を実行します:
code structly/structure.py

ファイルが開いたら、インポート文の最初の行を確認してください。現在は次のようになっています。

from validate import validate_type

この文は、ファイルが異なる構造にあったときは正しかったのですが、今では、同じパッケージ内で validate モジュールを探すように Python に指示する必要があります。そのため、次のように変更します。

from .validate import validate_type

ここで重要なのは、validate の前のドット (.) です。これは Python の相対インポートと呼ばれる特別な構文です。これは、現在のモジュール(この場合は structure.py)と同じパッケージ内で validate モジュールを探すように Python に指示します。

この変更を行った後、ファイルを保存してください。保存は、変更を永続化し、コードを実行したときに Python が更新されたインポート文を使用するため、重要です。

次に、他のファイルを確認して、更新が必要かどうかを確認しましょう。

  1. structly/reader.py - このファイルは、カスタムモジュールから何もインポートしていません。つまり、このファイルに変更を加える必要はありません。
  2. structly/tableformat.py - reader.py ファイルと同様に、このファイルもカスタムモジュールから何もインポートしていません。したがって、ここでも変更は必要ありません。
  3. structly/validate.py - 前の 2 つのファイルと同様に、カスタムモジュールから何もインポートしていません。したがって、変更する必要はありません。

実際のプログラミングでは、プロジェクトのモジュール間にはより複雑な関係がある場合があります。ファイルを移動してパッケージ構造を作成または変更する際は、常にインポート文を更新することを忘れないでください。これにより、コードが必要なモジュールを正しく見つけて使用できるようになります。

stock.py プログラムの更新とテスト

パッケージを作成し、内部のインポートを修正したので、次は stock.py ファイルを更新して新しいパッケージ構造を使用するようにしましょう。Python のパッケージは、関連するモジュールをまとめる方法です。これにより、コードベースを整理し、コードの管理と再利用が容易になります。

エディタで stock.py ファイルを開きます。

## Click on stock.py in the file explorer or run:
code stock.py

現在の stock.py のインポート文は、すべてのファイルが同じディレクトリにある古い構造を前提としています。Python でモジュールをインポートすると、Python は特定の場所でモジュールを探します。古い構造では、すべてのファイルが同じディレクトリにあったため、Python はモジュールを簡単に見つけることができました。しかし、新しいパッケージ構造では、structly パッケージ内のモジュールを Python に探す場所を教えるために、インポート文を更新する必要があります。

stock.py ファイルを以下のように更新します。

## stock.py

from structly.structure import Structure, String, PositiveInteger, PositiveFloat

class Stock(Structure):
    name = String()
    shares = PositiveInteger()
    price = PositiveFloat()

    @property
    def cost(self):
        return self.shares * self.price

    def sell(self, nshares: PositiveInteger):
        self.shares -= nshares

if __name__ == '__main__':
    from structly.reader import read_csv_as_instances
    from structly.tableformat import create_formatter, print_table
    portfolio = read_csv_as_instances('portfolio.csv', Stock)
    formatter = create_formatter('text')
    print_table(portfolio, ['name','shares','price'], formatter)

主な変更点は以下の通りです。

  1. from structure import Structure, String, PositiveInteger, PositiveFloatfrom structly.structure import Structure, String, PositiveInteger, PositiveFloat に変更しました。この変更により、Python は structly パッケージ内の structure モジュールを探すようになります。
  2. from reader import read_csv_as_instancesfrom structly.reader import read_csv_as_instances に変更しました。同様に、この変更により、Python は structly パッケージ内の reader モジュールを探すようになります。
  3. from tableformat import create_formatter, print_tablefrom structly.tableformat import create_formatter, print_table に変更しました。これにより、Python は structly パッケージ内の tableformat モジュールを見つけることができます。

これらの変更を加えたら、ファイルを保存します。ファイルを保存することは、変更を保存し、プログラムを実行するときに使用できるようにするために重要です。

では、更新したコードをテストして、すべてが正しく動作することを確認しましょう。

python stock.py

以下の出力が表示されるはずです。

      name      shares       price
---------- ---------- ----------
      MSFT        100      51.23
       IBM         50       91.1
      AAPL         75     145.89
      ACME        125     123.45
       HPE         75       32.2

この出力が表示されたら、おめでとうございます!Python パッケージを正常に作成し、コードを更新して使用することができました。これは、コードがよりモジュール化された方法で整理され、将来的なメンテナンスと拡張が容易になったことを意味します。

まとめ

この実験では、Python パッケージの作成と構造化方法を学びました。具体的には、コードの整理における Python パッケージの概念と有用性を理解し、基本的なパッケージ構造を作成し、Python モジュールを移動し、インポート文を更新し、パッケージを正しく使用するようにコードを修正しました。

これらのスキルは、大規模な Python アプリケーションを開発する上で不可欠です。適切なコードの整理は、重要性がますます高まります。Python パッケージは、関連するコードをまとめ、名前の衝突を回避し、コードの再利用性、保守性、共有性を向上させます。整然とした構造のパッケージは、Python の学習を続ける上で、プロフェッショナルな Python 開発の礎となります。