6.6。 モジュール
Pythonインタープリターを終了して再度入力すると、作成した定義(関数と変数)は失われます。 したがって、多少長いプログラムを作成する場合は、テキストエディターを使用してインタープリターの入力を準備し、代わりにそのファイルを入力として実行することをお勧めします。 これは、スクリプトの作成として知られています。 プログラムが長くなると、メンテナンスを容易にするために、プログラムをいくつかのファイルに分割することをお勧めします。 また、定義を各プログラムにコピーせずに、いくつかのプログラムで作成した便利な関数を使用することもできます。
これをサポートするために、Pythonには、定義をファイルに入れて、スクリプトまたはインタープリターのインタラクティブインスタンスで使用する方法があります。 このようなファイルはモジュールと呼ばれます。 モジュールからの定義は、他のモジュールまたはメインモジュール(トップレベルおよび計算機モードで実行されるスクリプトでアクセスできる変数のコレクション)にインポートできます。 。
モジュールは、Pythonの定義とステートメントを含むファイルです。 ファイル名は、接尾辞.py
が付加されたモジュール名です。 モジュール内では、モジュールの名前(文字列として)がグローバル変数__name__
の値として使用できます。 たとえば、お気に入りのテキストエディタを使用して、現在のディレクトリに次の内容のfibo.py
というファイルを作成します。
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
次に、Pythonインタープリターを入力し、次のコマンドを使用してこのモジュールをインポートします。
>>> import fibo
これは、fibo
で定義されている関数の名前を現在のシンボルテーブルに直接入力しません。 そこにモジュール名fibo
を入力するだけです。 モジュール名を使用して、次の機能にアクセスできます。
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
関数を頻繁に使用する場合は、ローカル名に割り当てることができます。
>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
6.1。 モジュールの詳細
モジュールには、実行可能ステートメントと関数定義を含めることができます。 これらのステートメントは、モジュールを初期化することを目的としています。 これらは、インポートステートメントでモジュール名が検出されたときに最初のでのみ実行されます。 1 (ファイルがスクリプトとして実行される場合にも実行されます。)
各モジュールには独自のプライベートシンボルテーブルがあり、モジュールで定義されているすべての関数によってグローバルシンボルテーブルとして使用されます。 したがって、モジュールの作成者は、ユーザーのグローバル変数との偶発的な衝突を心配することなく、モジュール内のグローバル変数を使用できます。 一方、自分が何をしているのかがわかっている場合は、モジュールの関数を参照するために使用されるのと同じ表記法modname.itemname
を使用してモジュールのグローバル変数に触れることができます。
モジュールは他のモジュールをインポートできます。 すべての import ステートメントをモジュール(またはスクリプト)の先頭に配置するのが通例ですが、必須ではありません。 インポートされたモジュール名は、インポートするモジュールのグローバルシンボルテーブルに配置されます。
モジュールからインポートするモジュールのシンボルテーブルに名前を直接インポートする import ステートメントの変形があります。 例えば:
>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
これは、インポートが取得されるモジュール名をローカルシンボルテーブルに導入しません(したがって、この例では、fibo
は定義されていません)。
モジュールが定義するすべての名前をインポートするためのバリアントもあります。
>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
これにより、アンダースコア(_
)で始まる名前を除くすべての名前がインポートされます。 ほとんどの場合、Pythonプログラマーはこの機能を使用しません。これは、不明な名前のセットがインタープリターに導入され、既に定義したものが隠されている可能性があるためです。
一般に、モジュールまたはパッケージから*
をインポートする方法は、コードの読み取りが困難になることが多いため、嫌われていることに注意してください。 ただし、インタラクティブセッションでの入力を節約するために使用しても問題ありません。
モジュール名の後にas
が続く場合、as
に続く名前はインポートされたモジュールに直接バインドされます。
>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
これは、import fibo
と同じ方法でモジュールを効果的にインポートしますが、fib
として使用できる点が異なります。
from を利用する場合にも、同様の効果で使用できます。
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
ノート
効率上の理由から、各モジュールはインタプリタセッションごとに1回だけインポートされます。 したがって、モジュールを変更する場合は、インタプリタを再起動する必要があります。または、インタラクティブにテストするモジュールが1つだけの場合は、 importlib.reload()を使用します。 import importlib; importlib.reload(modulename)
。
6.1.1。 モジュールをスクリプトとして実行する
でPythonモジュールを実行する場合
python fibo.py <arguments>
モジュール内のコードは、インポートした場合と同じように実行されますが、__name__
は"__main__"
に設定されています。 つまり、モジュールの最後にこのコードを追加すると、次のようになります。
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
コマンドラインを解析するコードは、モジュールが「メイン」ファイルとして実行された場合にのみ実行されるため、ファイルをスクリプトおよびインポート可能なモジュールとして使用できるようにすることができます。
$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34
モジュールがインポートされた場合、コードは実行されません。
>>> import fibo
>>>
これは、モジュールに便利なユーザーインターフェイスを提供するため、またはテスト目的(スクリプトとしてモジュールを実行してテストスイートを実行する)のいずれかでよく使用されます。
6.1.2。 モジュール検索パス
spam
という名前のモジュールがインポートされると、インタープリターは最初にその名前の組み込みモジュールを検索します。 見つからない場合は、変数 sys.path で指定されたディレクトリのリストでspam.py
という名前のファイルを検索します。 sys.path は、次の場所から初期化されます。
- 入力スクリプトを含むディレクトリ(またはファイルが指定されていない場合は現在のディレクトリ)。
- PYTHONPATH (シェル変数
PATH
と同じ構文のディレクトリ名のリスト)。 - インストールに依存するデフォルト。
ノート
シンボリックリンクをサポートするファイルシステムでは、入力スクリプトを含むディレクトリは、シンボリックリンクをたどった後に計算されます。 つまり、シンボリックリンクを含むディレクトリは、モジュール検索パスにではなく追加されます。
初期化後、Pythonプログラムは sys.path を変更できます。 実行中のスクリプトを含むディレクトリは、検索パスの先頭、標準ライブラリパスの前に配置されます。 これは、ライブラリディレクトリ内の同じ名前のモジュールの代わりに、そのディレクトリ内のスクリプトがロードされることを意味します。 交換を意図していない限り、これはエラーです。 詳細については、セクション標準モジュールを参照してください。
6.1.3。 「コンパイルされた」Pythonファイル
モジュールの読み込みを高速化するために、Pythonは各モジュールのコンパイル済みバージョンを__pycache__
ディレクトリにmodule.version.pyc
という名前でキャッシュします。バージョンはコンパイル済みファイルの形式をエンコードします。 通常、Pythonのバージョン番号が含まれています。 たとえば、CPythonリリース3.3では、spam.pyのコンパイル済みバージョンは__pycache__/spam.cpython-33.pyc
としてキャッシュされます。 この命名規則により、異なるリリースおよび異なるバージョンのPythonからコンパイルされたモジュールを共存させることができます。
Pythonは、ソースの変更日をコンパイル済みバージョンと照合して、ソースが古く、再コンパイルする必要があるかどうかを確認します。 これは完全に自動化されたプロセスです。 また、コンパイルされたモジュールはプラットフォームに依存しないため、同じライブラリを異なるアーキテクチャのシステム間で共有できます。
Pythonは、2つの状況でキャッシュをチェックしません。 まず、常に再コンパイルされ、コマンドラインから直接ロードされたモジュールの結果は保存されません。 次に、ソースモジュールがない場合はキャッシュをチェックしません。 非ソース(コンパイル済みのみ)ディストリビューションをサポートするには、コンパイル済みモジュールがソースディレクトリにある必要があり、ソースモジュールがあってはなりません。
専門家のためのいくつかのヒント:
- Pythonコマンドの -O または -OO スイッチを使用して、コンパイルされたモジュールのサイズを小さくすることができます。
-O
スイッチはassertステートメントを削除し、-OO
スイッチはassertステートメントと__doc__文字列の両方を削除します。 一部のプログラムはこれらを利用できることに依存している可能性があるため、このオプションは、自分が何をしているかを知っている場合にのみ使用してください。 「最適化された」モジュールにはopt-
タグがあり、通常は小さいです。 将来のリリースでは、最適化の効果が変わる可能性があります。 - プログラムは、
.pyc
ファイルから読み取られた場合、.py
ファイルから読み取られた場合よりも高速に実行されません。.pyc
ファイルの方が速いのは、ファイルの読み込み速度だけです。 - モジュール compileall は、ディレクトリ内のすべてのモジュールの.pycファイルを作成できます。
- PEP 3147 には、決定のフローチャートを含む、このプロセスの詳細があります。
6.2。 標準モジュール
Pythonには、別のドキュメントであるPythonライブラリリファレンス(以下「ライブラリリファレンス」)で説明されている標準モジュールのライブラリが付属しています。 一部のモジュールはインタープリターに組み込まれています。 これらは、言語のコアの一部ではないが、効率のため、またはシステムコールなどのオペレーティングシステムプリミティブへのアクセスを提供するために組み込まれている操作へのアクセスを提供します。 このようなモジュールのセットは、基盤となるプラットフォームにも依存する構成オプションです。 たとえば、 winreg モジュールはWindowsシステムでのみ提供されます。 1つの特定のモジュールは注意に値します: sys 。これはすべてのPythonインタープリターに組み込まれています。 変数sys.ps1
およびsys.ps2
は、プライマリおよびセカンダリプロンプトとして使用される文字列を定義します。
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>
これらの2つの変数は、インタプリタが対話モードの場合にのみ定義されます。
変数sys.path
は、モジュールのインタープリターの検索パスを決定する文字列のリストです。 これは、環境変数 PYTHONPATH から、または PYTHONPATH が設定されていない場合は組み込みのデフォルトから取得されたデフォルトパスに初期化されます) 。 標準のリスト操作を使用して変更できます。
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
6.3。 NS dir() 関数
組み込み関数 dir()は、モジュールが定義する名前を見つけるために使用されます。 文字列のソートされたリストを返します。
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
'__package__', '__stderr__', '__stdin__', '__stdout__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
'_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
'thread_info', 'version', 'version_info', 'warnoptions']
引数がない場合、 dir()は、現在定義している名前を一覧表示します。
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
変数、モジュール、関数など、すべてのタイプの名前がリストされていることに注意してください。
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', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
'__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
'all', 'any', 'ascii', 'bin', 'bool', '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']
6.4。 パッケージ
パッケージは、「点線のモジュール名」を使用してPythonのモジュール名前空間を構造化する方法です。 たとえば、モジュール名A.B
は、A
という名前のパッケージ内のB
という名前のサブモジュールを指定します。 モジュールを使用することで、異なるモジュールの作成者が互いのグローバル変数名を気にする必要がなくなるのと同様に、点線のモジュール名を使用することで、NumPyやPillowなどのマルチモジュールパッケージの作成者が互いのモジュール名を気にする必要がなくなります。 。
サウンドファイルとサウンドデータを均一に処理するためのモジュールのコレクション(「パッケージ」)を設計するとします。 さまざまなサウンドファイル形式があります(通常、拡張子で認識されます。たとえば、.wav
、.aiff
、.au
)。そのため、増え続けるコレクションを作成して維持する必要がある場合があります。さまざまなファイル形式間の変換のためのモジュールの。 サウンドデータに対して実行する可能性のあるさまざまな操作(ミキシング、エコーの追加、イコライザー機能の適用、人工ステレオエフェクトの作成など)も多数あるため、実行するモジュールの終わりのないストリームを作成します。これらの操作。 パッケージの可能な構造は次のとおりです(階層ファイルシステムで表されます)。
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
パッケージをインポートするとき、Pythonはsys.path
上のディレクトリを検索してパッケージサブディレクトリを探します。
__init__.py
ファイルは、Pythonでファイルを含むディレクトリをパッケージとして処理するために必要です。 これにより、string
などの一般的な名前のディレクトリが、後でモジュール検索パスで発生する有効なモジュールを意図せずに非表示にするのを防ぎます。 最も単純なケースでは、__init__.py
は空のファイルにすることができますが、パッケージの初期化コードを実行したり、後で説明する__all__
変数を設定したりすることもできます。
パッケージのユーザーは、パッケージから個々のモジュールをインポートできます。次に例を示します。
import sound.effects.echo
これにより、サブモジュールsound.effects.echo
がロードされます。 フルネームで参照する必要があります。
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
サブモジュールをインポートする別の方法は次のとおりです。
from sound.effects import echo
これにより、サブモジュールecho
もロードされ、パッケージプレフィックスなしで使用できるようになるため、次のように使用できます。
echo.echofilter(input, output, delay=0.7, atten=4)
さらに別のバリエーションは、目的の関数または変数を直接インポートすることです。
from sound.effects.echo import echofilter
繰り返しますが、これはサブモジュールecho
をロードしますが、これによりその機能echofilter()
が直接利用可能になります。
echofilter(input, output, delay=0.7, atten=4)
from package import item
を使用する場合、アイテムはパッケージのサブモジュール(またはサブパッケージ)、または関数、クラス、変数など、パッケージで定義されている他の名前のいずれかであることに注意してください。 import
ステートメントは、最初にアイテムがパッケージで定義されているかどうかをテストします。 そうでない場合は、それがモジュールであると想定し、ロードを試みます。 見つからない場合は、 ImportError 例外が発生します。
逆に、import item.subitem.subsubitem
のような構文を使用する場合、最後を除く各項目はパッケージである必要があります。 最後の項目はモジュールまたはパッケージにすることができますが、前の項目で定義されたクラス、関数、または変数にすることはできません。
6.4.1。 パッケージからのインポート*
ユーザーがfrom sound.effects import *
と書くとどうなりますか? 理想的には、これが何らかの形でファイルシステムに送信され、パッケージに存在するサブモジュールを見つけて、それらすべてをインポートすることを期待します。 これには長い時間がかかる可能性があり、サブモジュールをインポートすると、サブモジュールが明示的にインポートされた場合にのみ発生するはずの望ましくない副作用が発生する可能性があります。
唯一の解決策は、パッケージの作成者がパッケージの明示的なインデックスを提供することです。 import ステートメントは次の規則を使用します。パッケージの__init__.py
コードが__all__
という名前のリストを定義している場合、それは次の場合にインポートする必要があるモジュール名のリストと見なされます。 from package import *
が発生しました。 パッケージの新しいバージョンがリリースされたときにこのリストを最新の状態に保つのは、パッケージの作成者の責任です。 パッケージの作成者は、パッケージから*をインポートする用途が見当たらない場合は、サポートしないことを決定する場合もあります。 たとえば、ファイルsound/effects/__init__.py
には次のコードを含めることができます。
__all__ = ["echo", "surround", "reverse"]
これは、from sound.effects import *
がsound
パッケージの3つの名前付きサブモジュールをインポートすることを意味します。
__all__
が定義されていない場合、ステートメントfrom sound.effects import *
はパッケージsound.effects
から現在の名前空間にすべてのサブモジュールをインポートしませんしません。 パッケージsound.effects
がインポートされていることを確認し(__init__.py
で初期化コードを実行している可能性があります)、パッケージで定義されている名前をインポートするだけです。 これには、__init__.py
によって定義された(および明示的にロードされた)名前が含まれます。 また、以前の import ステートメントによって明示的にロードされたパッケージのサブモジュールも含まれます。 このコードを検討してください:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
この例では、echo
およびsurround
モジュールは、from...import
ステートメントの実行時にsound.effects
パッケージで定義されているため、現在の名前空間にインポートされます。 (これは、__all__
が定義されている場合にも機能します。)
特定のモジュールは、import *
を使用するときに特定のパターンに従う名前のみをエクスポートするように設計されていますが、それでも本番コードでは悪い習慣と見なされています。
from package import specific_submodule
を使用しても問題はないことを忘れないでください! 実際、インポートするモジュールが異なるパッケージの同じ名前のサブモジュールを使用する必要がない限り、これは推奨される表記法です。
6.4.2。 パッケージ内リファレンス
パッケージがサブパッケージに構造化されている場合(例のsound
パッケージのように)、絶対インポートを使用して兄弟パッケージのサブモジュールを参照できます。 たとえば、モジュールsound.filters.vocoder
がsound.effects
パッケージのecho
モジュールを使用する必要がある場合、from sound.effects import echo
を使用できます。
from module import name
形式のインポートステートメントを使用して、相対インポートを作成することもできます。 これらのインポートでは、先頭のドットを使用して、相対インポートに関係する現在のパッケージと親パッケージを示します。 たとえば、surround
モジュールから、次を使用できます。
from . import echo
from .. import formats
from ..filters import equalizer
相対インポートは、現在のモジュールの名前に基づいていることに注意してください。 メインモジュールの名前は常に"__main__"
であるため、Pythonアプリケーションのメインモジュールとして使用することを目的としたモジュールは、常に絶対インポートを使用する必要があります。
6.4.3。 複数のディレクトリのパッケージ
パッケージは、もう1つの特別な属性 __ path __ をサポートします。 これは、そのファイル内のコードが実行される前に、パッケージの__init__.py
を保持するディレクトリの名前を含むリストに初期化されます。 この変数は変更できます。 これを行うと、パッケージに含まれるモジュールおよびサブパッケージの今後の検索に影響します。
この機能はあまり必要ありませんが、パッケージに含まれるモジュールのセットを拡張するために使用できます。
脚注
- 1
- 実際、関数定義は「実行される」「ステートメント」でもあります。 モジュールレベルの関数定義を実行すると、モジュールのグローバルシンボルテーブルに関数名が入力されます。