モジュールとは
モジュールとは、関数のような機能をまとめ、必要な時に読み込んで使えるようにする仕組みです。
拡張子に.py
を指定したファイルなどに関数などを定義することでモジュールとして使用できます。
モジュールを使用するには、初めにimport
してモジュールを読み込む必要があります。
import math
math.sqrt(4) # sqrt()は平方根を計算するための関数
# 2.0
インポートの仕組み
モジュールのグローバル変数には、__name__=モジュール名
という内容が格納されています。
この__name__
にセットされているモジュール名を使ってimport モジュール名
を実行することで、そのモジュール内の関数が一度だけ実行されます。これにより、モジュール内に定義されている関数などが利用できるようになります。
globals()
関数で、importしてあるモジュールを確認できます。
globals()は、現在のグローバルスコープ内の全ての変数や関数を含む辞書を返す組み込み関数です。
globals()
# 'math': <module 'math' (built-in)>,
※globals()関数は、デバッグやインスペクション、動的な変数操作など、さまざまな目的で使用されます。ただし、グローバルスコープはプログラム内のどこからでもアクセス可能であるため、注意が必要です。プログラムの大規模化や保守性の向上を考える場合には、適切なスコープやモジュールの設計を検討することが重要です。
インポート方法
- モジュール自体をインポートする。
- モジュール内の関数を直接インポートする
- モジュール内の名前をすべて取り込む
→アンダーバー(_)
以外で始まるすべての関数やクラスがインポートされます。
import <モジュール名> # 1の例
import <モジュール名> from <関数名> # 2の例
import <モジュール名> from * # 3の例
モジュールをスクリプトとして実行する方法
①猫の年齢を人間の年齢に換算する関数を、別ファイルでcats_age.py
として作成する。
def cats_age(cat_age):
return 24 + (cat_age - 2) * 4
②このモジュールをスクリプトとして実行できるよう以下のコードを追記します。
if __name__ == "__main__":
import sys
print(cats_age(int(sys.argv[1])))
● 追記したコードの解説
-
__name__
変数は、モジュールの実行方法に応じて特定の値を持ちます。
直接実行されたスクリプトの場合、__name__
変数は"__main__"
となります。
この条件を利用して、スクリプトが直接実行されたか他のモジュールからインポートされたかを判断しています。 -
if __name__ == "__main__":
の条件文は、スクリプトが直接実行された場合のみ以下のコードブロックが実行されるようにします。ファイルをモジュールとしてではなくスクリプトとして実行したい場合は、この構文をモジュールに追記します。 -
import sys
は、Pythonの標準ライブラリであるsys
モジュールをインポートしています。このモジュールには、コマンドライン引数を取得するためのargv
属性が含まれています。 -
sys.argv[1]
は、スクリプトのコマンドライン引数の2番目(インデックス1)を取得しています。コマンドライン引数は文字列として渡されるため、int()
関数を使って整数に変換しています。 -
cats_age()
関数は、引数として与えられた年齢を使って、人間の年齢に換算する関数。 -
print(cats_age(int(sys.argv[1])))
は、cats_age()
関数に引数を渡してその結果を表示しています。
③Goolge Colaboratory(以下、Colabo)で実行してみる。
※Colaboで実行する場合は、先頭に!
をつける必要があります。
!python cats_age.py 3
# 28
※ここで、globals()関数を実行してみると、下記のようになっている。
globals()
# '!python cats_age.py 3',
モジュールの検索パスについて
モジュールの検索パスとは、Pythonがモジュールを探索するための場所や順序を定義するリストです。
● 基本的には、以下の4つの順で検索される。
-
組み込みモジュールの検索パス:
Pythonは最初に組み込みのモジュール(例:math
やsys
など)を検索します。これらのモジュールはPythonのインストールに含まれており、常に利用可能です。 -
カレントディレクトリの検索:
Pythonは現在の作業ディレクトリ(スクリプトが実行されたディレクトリ)を検索パスの最初に追加します。これにより、スクリプトと同じディレクトリにあるモジュールをインポートすることができます。 -
PYTHONPATHの検索:
PYTHONPATH
環境変数に指定されたディレクトリが、次に検索パスに追加されます。PYTHONPATH
環境変数は、カンマで区切られたディレクトリのリストを指定することができます。指定されたディレクトリ内のモジュールが利用可能となります。 -
インストールされたモジュールの検索:
Pythonは、Pythonのインストール場所やサードパーティライブラリのインストール場所など、事前に指定されたディレクトリを検索します。これにより、グローバルにインストールされたモジュールを利用できます。
● モジュールの検索パスはsys.path
に登録されています。
import sys
print(sys.path)
# ['/content', '/env/python', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages', '/usr/local/lib/python3.10/dist-packages/IPython/extensions', '/root/.ipython']
/content
は、Colaboでのデフォルトの作業フォルダです。
新規フォルダを作成して、そのフォルダでモジュールを作成して実行した場合
下記のようなエラーが発生することがあります。
# ModuleNotFoundError: No module named 'モジュール名'
これは、sys.path
にパスを追加していないためにエラーが発生しています。
sys.path
にパスを追加する必要があります。
import sys
sys.path.append("new_folder/") # new_folder/は新規フォルダ名
再度、sys.path
を確認すると、new_folderが追加されているのが分かります。
import sys
print(sys.path)
# ['/content', '/env/python', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages', '/usr/local/lib/python3.10/dist-packages/IPython/extensions', '/root/.ipython', 'new_folder/']
モジュールのキャッシュ機能について
Pythonには、コンパイル済みのモジュールをキャッシュすることでモジュールの読み込みを高速化する機能があります。コンパイル済みのモジュールは__pycache__
に保存されます。
Colaboで!ls -a
と実行すると、__pycache__
が作成されているか分かります。
作成されていない場合は、!python -m compileall
でモジュールのコンパイルを実行できます。
cats_age.py
をコンパイルしてみます。
!python -m compileall cats_age.py
!ls -a # 作成されたか確認
# . cats_age.py .ipynb_checkpoints __pycache__
# .. .config new_folder sample_data
__pycache__
の中身を確認してみます。
!ls __pycache__/
# cats_age.cpython-310.pyc
この.pyc
というファイルにコンパイル済みのモジュールがキャッシュされています。
Pythonではこのファイルを参照することで、モジュールの読み込みを高速化しています。
dir()関数について
dir()
関数は、オブジェクトが持つ属性やメソッドの一覧を返す組み込み関数です。これにより、Pythonのオブジェクトの構造や利用可能な属性やメソッドを調べることができます。
(モジュールが定義している名前を確認することができる。)
import cats_age
dir(cats_age)
# ['__builtins__','__cached__','__doc__','__file__','__loader__','__name__','__package__','__spec__','cats_age']
dir() 関数は、デバッグやオブジェクトの構造の理解、ドキュメントの調査など、さまざまな目的で使用されます。また、特定のオブジェクトの属性やメソッドを調べる際にも便利です。