Pythonのモジュールについて
ポイント
- モジュール=Pythonの定義や文が入ったファイル
- ファイル名は
*.py
- モジュールの中では、グローバル変数
__name__
の値としてモジュール名が設定されている
sample_module.py
def func1(n):
return n
def func2(n):
return n
Pythonのインタープリタにて
>>> import sample_module
>>> sample_module.func1('kawauso')
'kawauso'
モジュールのimportについて
ポイント
- モジュールには関数定義の他実行可能な文を入れることもできる
- これらの文はimport時に実行されるため初期化として使う
- モジュールはそれぞれがプライベートなシンボル表を持つため、呼び出し側との名前の衝突を気にする必要はない
- モジュール内のグローバル変数にアクセスするには、modulename.itemnameの形で書けばよい
- モジュールから他のモジュールも呼べる
- 慣例としてimport文はファイルの先頭に記載する
- モジュール内に定義されている名前を個別に呼び出すことも可能
>>> from sample_module import func1, func2
>>> func1('kawauso')
'kawauso'
>>> func2('kawauso')
'kawauso'
-
*
を使用すれば、モジュールが定義する_で始まる以外のすべての名前を取り込む - 一般的には何がimportされるのか一見して分かりづらいため、好まれない書き方である
>>> from sample_module import *
>>> func1('kawauso')
'kawauso'
モジュールをスクリプトとして実行する
ポイント
-
python sample_module.py 引数
にモジュールを実行することもできる - この時、
__name__
は__main__
になる - これを利用して、スクリプトとして実行された場合の分岐が書ける
sample_module.py
def func1(n):
return n
def func2(n):
return n
# モジュールとしてインポートされたときは、このコードは走らない
if __name__ == "__main__":
import sys
func1(sys.argv[1])
$ python sample_module.py kawauso
kawauso
モジュールの検索パス
ポイント
- モジュールがインポートされるとき、Pythonのインタープリタはまずビルトインモジュールを探しにいく
- 次にsys.path変数で得られるディレクトリのリストを使ってファイル名を検索する
- sys.pathは初期化後にプログラムから改変できる
- 実行中のスクリプトのあるディレクトリは、検索パスの最初に置かれる
- そのため、標準ライブラリと同名のモジュールがあれば、そちらが優先的にロードされる
コンパイル済みのPythonファイルについて
ポイント
- モジュール読み込みの高速化のため、Pythonはコンパイル済みのモジュールを
__pycache__
ディレクトリにキャッシュする - コンパイル済みのモジュールは
module.バージョン名.pyc
の名前でキャッシュされる - この命名規約によって異なるリリース、異なるバージョンのPythonでも共存できるようになっている
- Pythonはソースファイルの最終変更日時をコンパイル済みのバージョンと比較し、再コンパイルが必要かどうか判断している
標準モジュール
ポイント
- pythonには標準モジュールのライブラリが付属する
- モジュールにはインタープリタに組み込みのものもあり、性能上の必要性やOSプリミティブな処理を行うために組み込まれる
- これらはインストール時の設定や、プラットフォームによって決まる
- たとえば
winreg
モジュールはWindowsシステムにのみ提供される - こういったモジュールでは
sys
が代表的(これはすべてのPythonインタープリタで組み込みになっている) -
sys.ps1
,sys.ps2
などの変数はインタープリタが対話モードの時のみ定義されている -
sys.path
はインタープリタのモジュール検索パスを指定する文字列のリスト -
sys.path
はPYTHONPATH
か、組み込みのデフォルトパスとなっている - これは標準のリスト操作で改変可能
dir()関数
- ビルトイン関数
dir()
は、モジュールが定義している名前を確認するのに使う(返り値は文字列のリスト)
>>> import module
>>> dir(module)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'func1', 'func2']
- 引数なしの
dir()
は現在のレベルで定義されている名前のリストを返す
>>> hoge = 'hoge'
>>> dir()
['__annotations__', '__builtins__',
'__doc__', '__loader__', '__name__', '__package__', '__spec__', 'hoge',
'module']
>>>
-
dir()
はビルトインの関数名と変数名をリストアップしない - 確認したかったら、標準モジュール
builtins
を確認する
>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
'RecursionError', 'ReferenceError',
'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '_', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
パッケージ
ポイント
- パッケージは「ドット区切りモジュール名」を使ってPythonのモジュールを構築する方法
- 例えばモジュール名
A.B
は、パッケージ「A」にあるサブモジュール「B]を指す - あるディレクトリをパッケージを含むものと扱わせるには
__init__.py
ファイルが必要 -
__init__.py
は単なる空ファイルとすることもできるが、パッケージの初期化コードを実行したり、__all__
変数をセットすることもできる
パッケージ構成の例
A/ -> トップレベルパッケージ
__init__.py -> パッケージの初期化
A1/ -> サブパッケージ1
__init__.py
hoge1.py
hoge2.py
hoge3.py
A2/ -> サブパッケージ2
__init__.py
hoge1.py
hoge2.py
hoge3.py
パッケージの読み込み
import A.A1.hoge1
# これに対する参照はフルネームで行う必要がある
A.A1.hoge1.func1()
また、別のロード方法もある
パッケージの読み込み2
from A.A1 import hoge1
hoge1.func1()
さらに、目的の関数や変数を直接インポートする方法もある
from A.A1.hoge1 import func1
func1()
パッケージから*をインポート
ポイント
-
from A.A1 import *
とするとき、パッケージの__init__.py
のコードが__all__
変数を定義していた場合、そこに定義されたパッケージをimportする -
__all__
が定義されていないときは、A.A1
のインポートと、パッケージ本体で定義されているすべての名前のインポートのみ -
__init__.py
で定義された名前もインポートされる
__init__.py
__all__ = ["module1", "module2", "module3"]
module4 = func4() # module4もインポートされる
- それまでのimport文で明示的にロードされていたサブモジュールがあれば、それもインポートされる
# echoおよびsurroundモジュールがインポートされる
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
パッケージ内の相互参照
ポイント
- パッケージがサブパッケージにより構成されているとき、姉妹パッケージの参照は絶対インポートの他、相対インポートも可能
- 相対インポートはカレントのモジュールに基づいて行われるので、メインモジュールからは必ず絶対インポートを使うこと
- メインモジュールの名前は常に
__main__
となる
from . import echo # 同じ階層
from .. import formats # 1つ上の階層
from ..filters import equalizer # 1つ上の階層のfiltersサブモジュール内
複数のディレクトリにまたがるパッケージ
ポイント
-
__path__
は書き換えることでパッケージに含まれるモジュールやサブパッケージの検索に影響を与える - パッケージが持つモジュールの集合を拡張したいときに使える