SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

レトロ風ゲームを作って学ぶPython入門

【作って学ぶPython】プログラムを書いて、モジュールやパッケージで整理しよう!

レトロ風ゲームを作って学ぶPython入門 第3回


  • X ポスト
  • このエントリーをはてなブックマークに追加

モジュールとパッケージ

 すでに標準ライブラリや、pipのパッケージをimport文で読み込む方法は紹介しました。ここではimportを使い、自分で書いた別ファイルのプログラムを読み込む方法を紹介します。

別ファイルの読み込み

 最もシンプルな例です。

 同じディレクトリ階層にあるsub.pyというファイルは、import文を使い、import subと書いて読み込めます。このときsub.pyはモジュールといいます。そしてsub.py内にある変数や関数は、sub.get()のように、.区切りで変数や関数を書いて利用できます。

 ファイル構成とプログラムの例を示します。

ファイル構成
main.py
sub.py
main.py
import sub

print(sub.name)     # 「SUB」と表示
print(sub.get())    # 「subです」と表示
sub.py
name = "SUB"

def get():
    return "subです"

フォルダー内のファイルの読み込み

 次のようなファイル構成になっているとします。

ファイル構成
main.py
tool/
    sub.py

 このときmain.pyからtool/sub.pyは、tool.subとして読み込めます。フォルダーの階層は.で区切ります。

main.py
import tool.sub

print(tool.sub.name)     # 「SUB」と表示
print(tool.sub.get())    # 「subです」と表示
sub.py
name = "SUB"

def get():
    return "subです"

 また、fromを利用して、指定のパスから、モジュール、関数、変数を読み込むこともできます。

 次のプログラムは、toolからsubをインポートする例と、tool.subからnamegetをインポートする例です。

main.py
from tool import sub    # toolからsubをインポート

print(sub.name)     # 「SUB」と表示
print(sub.get())    # 「subです」と表示
main.py
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

 次に各ファイルの中身です。

main.py
import tool

print(tool.sub1.get())  # 「sub1です」と表示
print(tool.sub2.get())  # 「sub2です」と表示
__init__.py
from . import sub1, sub2
sub1.py
def get():
    return "sub1です"
sub2.py
def get():
    return "sub2です"

 __init__.pyでは、from . import sub1, sub2のように書いています。.は自身のフォルダーを表しています。.は自身、..は1つ上の意味です。from . import sub1, sub2は、同じフォルダー内のsub1.pysub2pyを読み込みます。

モジュールの検索

 少し高度な説明なので、ここは読み飛ばしてもよいです。

 モジュールの検索は、sys.pathリストにあるフォルダー内から探します。import subと書くと、sys.pathリスト内の各フォルダーをルートにしてsub.pyを探します。

 sys.pathリストには、プログラムの開始ファイルのフォルダーや、Pythonの標準ライブラリやpipのインストール先などが含まれます。

 プログラムと出力の例を示します。

C:/sample_code/test/sys_path/test.py
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.pyimport sub1と書くと、見つからずにエラーが出ます。

 開始ファイルのあるルートからimport tool.sub1のように書くか、from . import sub1という相対パスで指定すると読み込めます。

 検証用のプログラムを示します。ファイル構成と、各ファイルのプログラムと出力です。

ファイル構成
main.py
tool/
    sub1.py
    sub2.py
    sub3.py
    sub4.py
main.py
import tool.sub2
import tool.sub3
import tool.sub4
sub1.py
def get(from_mod):
    return f"sub1 from {from_mod}"
sub2.py
import tool.sub1
print(tool.sub1.get("sub2"))
sub3.py
from . import sub1
print(sub1.get("sub3"))
sub4.py
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.pysub3.pyでは、sub1.pyを読み込めます。最後のsub4.pyでは、import sub1と書いた部分のsub1が見つからないとエラーが出ます。

 import hogeのように短い名前だけを書いて読み込めるのは、標準ライブラリ、pipでインストールしたパッケージ、開始ファイルと同じ階層のモジュールやパッケージといった限られたものだけです。それ以外は、ルートからの階層を指定するか、相対パスで書く必要があります。

 また、開始ファイルのあるトップレベルのフォルダーをまたいで他のフォルダーのファイルを読み込むには、変則的なコードを書く必要があります。入門者向けではないので、ここでは説明を割愛します。

asによる名前の置き換え

 インポートしたものには違う名前を付けることができます。

 複数のモジュールを読み込んだときに、名前が被ることがあります。そのときは、名前を別のものに変更しなければなりません。また、長すぎる名前のモジュールを読み込んだときに、短い名前に変更したいこともあるでしょう。

 そうしたときに役立つのがasです。asを使うことで、別の名前として、モジュールや、モジュール内の変数や関数を読み込めます。

main.py
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
a.py
import tool.b

print("a.py", __file__)
print("a.py", __name__)
b.py
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のいくつかの機能を確認していきます。サンプルのプログラムでは、今回学んだ関数の宣言を利用します。

次のページ
画像描画

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
レトロ風ゲームを作って学ぶPython入門連載記事一覧

もっと読む

この記事の著者

柳井 政和(ヤナイ マサカズ)

クロノス・クラウン合同会社 代表社員http://crocro.com/オンラインソフトを多数公開。プログラムを書いたり、ゲームを作ったり、記事を執筆したり、マンガを描いたり、小説を書いたりしています。「めもりーくりーなー」でオンラインソフト大賞に入賞。最近は、小説家デビューして小説も書いています(『裏切りのプログラム』他)。面白いことなら何でもOKのさすらいの企画屋です。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/19457 2024/06/10 12:26

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング