モジュールとパッケージ
すでに標準ライブラリや、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のいくつかの機能を確認していきます。サンプルのプログラムでは、今回学んだ関数の宣言を利用します。

