完成したプログラムをPythonで実行したい時、良く使われるのが python.exe の引数に指定する方法です。
ファイルが1つだけなら気にする必要はありませんが、ちゃんとしたアプリケーションを作ろうとした時は自作モジュールやパッケージなどを含む複数ファイルになってしまい、正しいルールに従わないと思った通り動いてくれません。
今回は、複数ファイルで構成されるアプリケーションを実行する場合、最低限気を付けておくべきフォルダ構成やルールについて解説します。
必要最小限のフォルダ構成
最初に、必要最小限のフォルダ構成を示しておきます。
例えば、会計処理なら 「Accounting」とか、画像認識なら「ImageRecognition」など、何をするプログラム(アプリケーション)かを表す名前を考え、これをプロジェクト名にします。
プロジェクト名が決まったら、次にプロジェクト名でフォルダを作成します。
下図は「myproject」という名前のプロジェクトを作る場合の例です。
プログラムだけを格納するのであれば階層は1つだけでも良いのですが、将来このプロジェクトに関するドキュメント類やデータ、ログやテストプログラム、サンプルプログラムなどを作った場合、まとめて一か所に保存しておきたいので、あえてこのようなフォルダ構成にしておきます。
フォルダ構成についてはこちらの記事に詳しく記載していますので、もし良ければご一読下さい。
プログラムの実行方法
プログラムを実行するには、プロジェクトフォルダにカレントディレクトリを移動し、次のコマンドを実行します。
Python プロジェクト名
もしくは
Python -m プロジェクト名
例えば、プロジェクト名が myproject の場合、そこにカレントディレクトリを移動し、次のどちらかを実行します。
mオプションを付ける場合と付けない場合の違いについては、後ほど詳しく説明します。
1 2 3 4 5 |
# mオプション無しで実行 python myproject # mオプション有りで実行 python -m myproject |
プログラムを格納するフォルダに関するのルール
ここでは、パッケージを1つ持たせた場合のフォルダ構成を例に、暗黙のルールと特別なファイルについて説明します。
プログラムは第2階層の「プロジェクト名」フォルダに集める
Pythonでは、プログラムは第2階層の「プロジェクト名」フォルダに集めることが推奨されています。
下図では、それに従って「第2階層のプロジェクト名フォルダ配下」にパッケージを置いています。
もし複数のプロジェクトで共通に使うパッケージがある場合はこの限りではありませんので、別途適切な場所にフォルダを作って、そこに格納すれば良いかと思います。
特別なファイル
第2階層の「プロジェクト名」フォルダにプログラムを置く上で、とても重要なファイルが2つ存在します。
それは、 __init__.py と __main__.py です。
フォルダを作成してそこにプログラムを格納する場合、必ず __init__.py を作ることが推奨されています。
また、第2階層の「プロジェクト名」フォルダには、__main__.py を置くことが推奨されています。
それでは、それぞれについて詳しく見ていきましょう。
__init__.py
__init__.py は、そのフォルダをパッケージとして認識するためのマーカーであり、且つ外部のプログラムがパッケージをimport する時のコンストラクタの役目を持っています。
Pythonにとっては、第2階層の「プロジェクト名」フォルダも1つのパッケージとみなすことが出来るため、ここにも __init__.py を作っておきます。
__init__.py の中身は空でも問題はありませんが、多くの場合は使いたいパッケージの import を記述します。
1 2 3 4 |
# __init__.py の例 import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..')) |
特にパッケージに対しては、そのパッケージに含まれるモジュールを import するような記述になります。
__main__.py
__main__.py はプログラムのエントリーポイントです。
python の引数に実行したいファイル名を指定すると、そのファイルが直接実行されますが、フォルダ名(プロジェクト名) が渡されると、__main__.py が実行されます。
コード量が多いと __main__.py が肥大化しすぎるため、そのような場合は別途メイン処理のモジュールを用意して、__main__.py の中からは、単純にそれを呼ぶだけにするのがベストです。
m オプションの有無による動作の違い
Python フォルダ名 と python -m フォルダ名の違いはいくつかありますが、一番大きな違いは__init__.py が呼ばれるか否かの違いです。
アプリケーションにおいて、初期処理を __main__.py に記述するから __init__.py は不要というのであれば、m オプション無しで起動すれば良いかと思います。
もし、初期処理を __init__.py に記述するのであれば、m オプションを付けないと実行されません。
サンプルフォルダ構成と各ファイルの内容
下記は自作パッケージを1つ含むシンプルなプロジェクトのフォルダ構成例です。
__init__.py では、自作パッケージをインポートするための検索パスを登録しており、__main__.py にアプリケーションとしての処理を記述しています。
mylib は自作パッケージのフォルダですが、ここの __init__.py では呼び出した時点で、自作モジュールを import させる記述になっています。
第2階層myproject直下の__init__.py のサンプル
1 2 3 |
import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..')) |
エントリポイント(第2階層myproject直下の__main__.py) のサンプル
1 2 |
import mylib print(message(’hogehoge')) |
自作パッケージ(mylib)の __init__.py のサンプル
1 |
from mylib.mymodule import * |
自作パッケージ(mylib)に格納されたモジュール(mymodule)のサンプル
1 2 |
def message(x): print('output:',x) |
まとめ
今回は、Python.exe の引数にファイルを指定して実行させることを前提にした場合、どのようなフォルダ構成が望ましく、どんなルールがあるのかについて解説しました。
- 第2階層の「プロジェクト名」フォルダにプログラム一式を集めること
- __init__.pyはパッケージとしてのマーカーとコンストラクタの役割を持つ
- __main__.py はアプリケーションのエントリポイント
- Python.exe で m オプションの有無の差は、__init__.py が呼ばれるか否かの差
今回の記事が皆さんのPython独学の一助となれば幸いです。
コメント