モジュールとパッケージ
すでに標準ライブラリや、pipのパッケージをimport
文で読み込む方法は紹介しました。ここではimport
を使い、自分で書いた別ファイルのプログラムを読み込む方法を紹介します。
別ファイルの読み込み
最もシンプルな例です。
同じディレクトリ階層にあるsub.py
というファイルは、import
文を使い、import sub
と書いて読み込めます。このときsub.py
はモジュールといいます。そしてsub.py
内にある変数や関数は、sub.get()
のように、.
区切りで変数や関数を書いて利用できます。
ファイル構成とプログラムの例を示します。
main.py sub.py
import sub print(sub.name) # 「SUB」と表示 print(sub.get()) # 「subです」と表示
name = "SUB" def get(): return "subです"
フォルダー内のファイルの読み込み
次のようなファイル構成になっているとします。
main.py tool/ sub.py
このときmain.py
からtool/sub.py
は、tool.sub
として読み込めます。フォルダーの階層は.
で区切ります。
import tool.sub print(tool.sub.name) # 「SUB」と表示 print(tool.sub.get()) # 「subです」と表示
name = "SUB" def get(): return "subです"
また、from
を利用して、指定のパスから、モジュール、関数、変数を読み込むこともできます。
次のプログラムは、tool
からsub
をインポートする例と、tool.sub
からname
とget
をインポートする例です。
from tool import sub # toolからsubをインポート print(sub.name) # 「SUB」と表示 print(sub.get()) # 「subです」と表示
from tool.sub import name, get # tool.subからnameとgetをインポート print(name) # 「SUB」と表示 print(get()) # 「subです」と表示
フォルダーのみを指定して読み込み
フォルダーを作ってプログラムを分けた場合、フォルダー内のファイルが1つだけということはあまりないでしょう。フォルダーの中に、いくつかのファイルを作るのが一般的でしょう。
その際、import tool
とフォルダー名tool
だけを書き、tool.sub1.get()
のようにモジュールを利用できると便利です。
こうした方法は、フォルダー内に__init__.py
という特殊なファイルを作ると実現できます。こうした__init__.py
のあるフォルダーのことをパッケージと呼びます。
(古いPythonでは、フォルダー内のファイルを読み込むには、そのフォルダー内に__init__.py
が必要でした。しかし今のPythonでは、前項の説明のように__init__.py
がなくても大丈夫です。)
import tool
のようにパッケージ名を指定したときは、そのフォルダー内の__init__.py
が暗黙的に読み込まれます。この__init__.py
内で読み込んだモジュールは、パッケージを読み込んだ場所で利用できます。
プログラムの例を示します。まずはファイル構成です。
main.py tool/ __init__.py sub1.py sub2.py
次に各ファイルの中身です。
import tool print(tool.sub1.get()) # 「sub1です」と表示 print(tool.sub2.get()) # 「sub2です」と表示
from . import sub1, sub2
def get(): return "sub1です"
def get(): return "sub2です"
__init__.py
では、from . import sub1, sub2
のように書いています。.
は自身のフォルダーを表しています。.
は自身、..
は1つ上の意味です。from . import sub1, sub2
は、同じフォルダー内のsub1.py
とsub2py
を読み込みます。
モジュールの検索
少し高度な説明なので、ここは読み飛ばしてもよいです。
モジュールの検索は、sys.path
リストにあるフォルダー内から探します。import sub
と書くと、sys.path
リスト内の各フォルダーをルートにしてsub.py
を探します。
sys.path
リストには、プログラムの開始ファイルのフォルダーや、Pythonの標準ライブラリやpipのインストール先などが含まれます。
プログラムと出力の例を示します。
import sys for p in sys.path: print(p)
C:\sample_code\test\sys_path C:\(略)\Python\Python312\python312.zip C:\(略)\Python\Python312\DLLs C:\(略)\Python\Python312\Lib C:\(略)\Python\Python312 C:\(略)\Python\Python312\Lib\site-packages
こうしたパスから探索するため、先ほどのtool
パッケージ内で同じ階層のsub1.py
をimport sub1
と書くと、見つからずにエラーが出ます。
開始ファイルのあるルートからimport tool.sub1
のように書くか、from . import sub1
という相対パスで指定すると読み込めます。
検証用のプログラムを示します。ファイル構成と、各ファイルのプログラムと出力です。
main.py tool/ sub1.py sub2.py sub3.py sub4.py
import tool.sub2 import tool.sub3 import tool.sub4
def get(from_mod): return f"sub1 from {from_mod}"
import tool.sub1 print(tool.sub1.get("sub2"))
from . import sub1 print(sub1.get("sub3"))
import sub1 print(sub1.get("sub4"))
sub1 from sub2 sub1 from sub3 Traceback (most recent call last): File "(略)\main.py", line 3, in <module> import tool.sub4 File "(略)\tool\sub4.py", line 1, in <module> import sub1 ModuleNotFoundError: No module named 'sub1'
sub2.py
とsub3.py
では、sub1.py
を読み込めます。最後のsub4.py
では、import sub1
と書いた部分のsub1
が見つからないとエラーが出ます。
import hoge
のように短い名前だけを書いて読み込めるのは、標準ライブラリ、pipでインストールしたパッケージ、開始ファイルと同じ階層のモジュールやパッケージといった限られたものだけです。それ以外は、ルートからの階層を指定するか、相対パスで書く必要があります。
また、開始ファイルのあるトップレベルのフォルダーをまたいで他のフォルダーのファイルを読み込むには、変則的なコードを書く必要があります。入門者向けではないので、ここでは説明を割愛します。
asによる名前の置き換え
インポートしたものには違う名前を付けることができます。
複数のモジュールを読み込んだときに、名前が被ることがあります。そのときは、名前を別のものに変更しなければなりません。また、長すぎる名前のモジュールを読み込んだときに、短い名前に変更したいこともあるでしょう。
そうしたときに役立つのがas
です。as
を使うことで、別の名前として、モジュールや、モジュール内の変数や関数を読み込めます。
import tool.sub as s print(s.get()) # 「subです」と表示 from tool.sub import get as g print(g()) # 「subです」と表示
__file__と__name__
パッケージやモジュールに機能を分割していくと、プログラム自身のパスや名前を知りたいときがあります。
そのときには__file__
を使います。__file__
には、このプログラム自身の絶対パスが入っています。
また、__name__
には"tool.b"
のような名前が入っています。プログラムの開始ファイルは特別で、__name__
には"__main__"
という名前が入っています。
プログラムの例を示します。ファイル構成と、各ファイルのプログラム、出力の例です。python a.py
で実行します。
a.py tool/ b.py
import tool.b print("a.py", __file__) print("a.py", __name__)
print("b.py", __file__) print("b.py", __name__)
b.py C:\(省略)\tool\b.py b.py tool.b a.py C:\(省略)\a.py a.py __main__
キャッシュ
自作モジュールをインポートすると__pycache__
というディレクトリと、.pyc
という拡張子のファイルが作られます。この生成を避ける方法はいくつかあります。
手軽な方法はpython
コマンドに-B
(大文字)のフラグを付けることです。python -B main.py
のように書いて実行します。
以降は、Pygameのいくつかの機能を確認していきます。サンプルのプログラムでは、今回学んだ関数の宣言を利用します。