Python3 モジュール

これまでの章では基本的に Python インタープリタでプログラミングしてきました。Python インタープリタから一度終了して再度入り直すと、定義したすべてのメソッドと変数は消えてしまいます。

このために Python は、これらの定義をファイルに保存しておく方法を提供しています。スクリプトや対話型インタープリタのインスタンスが使用するためのこのファイルをモジュールと呼びます。

Python におけるモジュール(Module)は、Python の定義と文を含むファイルであり、ファイル名はモジュール名に.py拡張子を付けたものです。

モジュールには、関数、クラス、変数、および実行可能なコードを含めることができます。モジュールを使用することで、コードを再利用可能なユニットに整理でき、管理と保守が容易になります。

モジュールの役割

  • コードの再利用:よく使う機能をモジュールにカプセル化することで、複数のプログラムで繰り返し使用できます。

  • 名前空間の管理:モジュールは名前の衝突を防ぎます。異なるモジュール内の同名の関数や変数は互いに干渉しません。

  • コードの整理:機能ごとにコードを異なるモジュールに分割することで、プログラムの構造がより明確になります。

以下は、Python 標準ライブラリのモジュールを使用する例です。

例(Python 3.0+)

#!/usr/bin/python3 # 文件名: using_sys.py import sys print('コマンドライン引数は次のとおりです:') for i in sys.argv: print(i) print('\n\nPython のパスは次のとおりです:', sys.path, '\n')

実行結果は次のとおりです:

$ python using_sys.py 参数1 参数2
命令行参数如下:
using_sys.py
参数1
参数2


Python 路径为: ['/root', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages'] 

  • 1、import sys は Python 標準ライブラリの sys.py モジュールを取り込みます。これはあるモジュールをインポートする方法です。
  • 2、sys.argv はコマンドライン引数を含むリストです。
  • 3、sys.path は Python インタープリタが必要なモジュールを自動的に検索するパスのリストを含んでいます。

import 文

Python ソースファイルを使用したい場合は、別のソースファイル内で import 文を実行するだけで済みます。構文は次のとおりです:

import module1[, module2[,... moduleN]

インタープリタが import 文に遭遇したとき、モジュールが現在の検索パスにあればインポートされます。

検索パスは、インタープリタが最初に検索するすべてのディレクトリのリストです。モジュール support をインポートしたい場合は、コマンドをスクリプトの先頭に置く必要があります:

support.py ファイルのコード

#!/usr/bin/python3 # Filename: support.py def print_func( par ): print ("Hello : ", par) return

test.py が support モジュールをインポート:

test.py ファイルのコード

#!/usr/bin/python3 # Filename: test.py # 导入模块 import support # モジュールに含まれる関数を呼び出せるようになりました support.print_func("サンプル")

上記の例の出力結果:

$ python3 test.py 
Hello :  サンプル

コードをダウンロード

モジュールは、import を何回実行しても一度だけインポートされます。import。これにより、インポートされたモジュールが何度も実行されるのを防ぎます。

import 文を使用するとき、Python インタープリタはどうやって対応するファイルを見つけるのでしょうか?

これは Python の検索パスに関係します。検索パスは一連のディレクトリ名で構成され、Python インタープリタはこれらのディレクトリから順にインポートするモジュールを探します。

モジュールの検索パス

モジュールをインポートするとき、Python は次の順序でモジュールを検索します:

  1. 現在のディレクトリ。

  2. 環境変数PYTHONPATHで指定されたディレクトリ。

  3. Python 標準ライブラリのディレクトリ。

  4. .pthファイルで指定されたディレクトリ。

検索パスは Python のコンパイル時またはインストール時に決定され、新しいライブラリをインストールすると変更されることもあります。検索パスは sys モジュール内の path 変数に格納されています。簡単な実験として、対話型インタープリタで次のコードを入力してください:

>>> import sys
>>> sys.path
['', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']
>>> 

sys.path の出力はリストで、その最初の項目は空文字列 '' であり、現在のディレクトリを表します(スクリプトから出力した場合は、どのディレクトリであるかがより明確にわかります)。つまり、Python インタープリタを実行したディレクトリです(スクリプトの場合は、実行中のスクリプトがあるディレクトリです)。

したがって、私のように現在のディレクトリにインポート予定のモジュールと同名のファイルが存在する場合、インポートしようとするモジュールは遮蔽されてしまいます。

検索パスの概念を理解すれば、スクリプト内で変更して、sys.path検索パスにない一部のモジュールをインポートできます。

次に、インタープリタの現在のディレクトリ、または sys.path 内のいずれかのディレクトリに fibo.py ファイルを作成します。コードは次のとおりです:

例

# フィボナッチ(fibonacci)数列モジュール def fib(n): # n までフィボナッチ数列を定義する a, b = 0, 1 while b < n: print(b, end=' ') a, b = b, a+b print() def fib2(n): # n までのフィボナッチ数列を返す result = [] a, b = 0, 1 while b < n: result.append(b) a, b = b, a+b return result

次に Python インタープリタに入り、次のコマンドでこのモジュールをインポートします:

>>> import fibo

この方法では、fibo 内に直接定義された関数名は現在のシンボルテーブルに書き込まれず、モジュール名 fibo だけがそこに書き込まれます。

モジュール名を使って関数にアクセスできます:

例

>>>fibo.fib(1000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fibo.fib2(100) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibo.__name__ 'fibo'

ある関数を頻繁に使う予定なら、それをローカル名に代入することができます:

>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377


from … import 文

Python の from 文を使用すると、モジュールから指定した部分を現在の名前空間にインポートできます。構文は次のとおりです:

from modname import name1[, name2[, ... nameN]]

たとえば、モジュール fibo の fib 関数をインポートするには、次の文を使用します:

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

この宣言は fibo モジュール全体を現在の名前空間にインポートするのではなく、fibo 内の fib 関数だけを取り込みます。

モジュールにエイリアスを付ける

as キーワードを使用してasモジュールや関数にエイリアスを付けます:

import numpy as np  # 将 numpy 模块别名设置为 np
from math import sqrt as square_root  # 将 sqrt 函数别名设置为 square_root


from … import * 文

モジュールのすべての内容を現在の名前空間にインポートすることも可能です。次の宣言を使用するだけです:

from modname import *

これにより、モジュール内のすべての項目をインポートする簡単な方法が提供されます。

推奨されません。名前の衝突を引き起こしやすいためです。


モジュールを深く理解する

モジュールにはメソッド定義のほかに、実行可能なコードを含めることもできます。このコードは通常、モジュールを初期化するために使われます。このコードは最初にインポートされたときだけ実行されます。

各モジュールには独立したシンボルテーブルがあり、モジュール内部ではすべての関数のグローバルシンボルテーブルとして使用されます。

したがって、モジュールの作者は、他のユーザーのグローバル変数と混同する心配をせずに、モジュール内部でこれらのグローバル変数を安心して大胆に使用できます。

別の観点から言うと、本当に何をしているのか分かっている場合は、modname.itemname という表記法でモジュール内の関数にアクセスすることもできます。

モジュールは他のモジュールをインポートできます。モジュール(またはスクリプト、その他の場所)の先頭で import を使ってモジュールをインポートします。もちろんこれは慣例にすぎず、強制ではありません。インポートされたモジュールの名前は、現在操作しているモジュールのシンボルテーブルに置かれます。

もう1つのインポート方法として、import を使ってモジュール内の(関数や変数の)名前を現在操作しているモジュールに直接インポートできます。例:

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

このインポート方法では、インポートされたモジュールの名前は現在のシンボルテーブルに置かれません(したがって、この例では fibo という名前は定義されません)。

もう1つの方法として、モジュール内のすべての(関数、変数)名前を一度に現在のモジュールのシンボルテーブルにインポートできます:

>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

これによりすべての名前がインポートされますが、単一のアンダースコア(_)で始まる名前は含まれません。ほとんどの場合、Python プログラマーはこの方法を使用しません。他のソースから取り込んだ名前が既存の定義を上書きする可能性が高いからです。


__name__ 属性

モジュールが別のプログラムによって最初にインポートされるとき、その主プログラムが実行されます。

モジュールがインポートされたときに、モジュール内の特定のプログラムブロックを実行したくない場合は、__name__属性を使用して、そのプログラムブロックをそのモジュール自身が実行されるときにのみ実行させることができます。

#!/usr/bin/python3
# Filename: using_name.py

if __name__ == '__main__':
   print('程序自身在运行')
else:
   print('我来自另一模块')

実行出力は次のとおりです:

$ python using_name.py
程序自身在运行
$ python
>>> import using_name
我来自另一模块
>>>

説明:各モジュールには __name__ 属性があります。

  • モジュールが直接実行された場合、__name__その値は__main__。

  • モジュールがインポートされた場合、__name__その値はモジュール名です。

説明:__name__と__main__その前後は二重アンダースコアです、_ ___name__ はこのように中間のスペースを取り除いたものです。


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']
>>> a = 5 # 建立一个新的变量 'a'
>>> dir()
['__builtins__', '__doc__', '__name__', 'a', 'sys']
>>>
>>> del a # 删除变量名a
>>>
>>> dir()
['__builtins__', '__doc__', '__name__', 'sys']
>>>

標準モジュール

Python 自体には標準のモジュールライブラリがいくつか付属しており、それらは Python ライブラリリファレンスドキュメント(後の「ライブラリリファレンスドキュメント」)で紹介されます。

モジュール名機能の説明
math数学演算(平方根、三角関数など)
osオペレーティングシステム関連の機能(ファイル操作、ディレクトリ操作など)
sysシステム関連のパラメータと関数
random乱数の生成
datetime日付と時刻の処理
jsonJSON データの処理
re正規表現操作
collections追加のデータ構造(defaultdict、deque など)を提供
itertoolsイテレータツールを提供
functools高階関数ツール(reduce、lru_cache など)を提供

一部のモジュールはインタープリタに直接組み込まれています。これらは言語の組み込み機能ではありませんが、非常に効率的に使用でき、システムレベルの呼び出しでも問題ありません。

これらのコンポーネントは、オペレーティングシステムに応じて異なる形で構成されます。たとえば、winreg モジュールは Windows システムにのみ提供されます。

特別なモジュール sys がすべての Python インタープリタに組み込まれていることに注意してください。変数 sys.ps1 と sys.ps2 は、メインプロンプトとサブプロンプトに対応する文字列を定義します:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('サンプル!')
サンプル!
C> 

包

パッケージは、「ドット付きモジュール名」を使用して Python モジュールの名前空間を管理する形式です。

たとえば、モジュール名が A.B の場合、それはパッケージ A 内のサブモジュール B を表します。

モジュールを使用するときに、異なるモジュール間のグローバル変数が互いに影響することを心配する必要がないのと同様に、ドット付きモジュール名という形式を採用しても、異なるライブラリ間でモジュール名が重複することを心配する必要はありません。

これにより、さまざまな作者が NumPy モジュールや Python グラフィックライブラリを提供できます。

音声ファイルとデータを統一的に処理するモジュール群(または「パッケージ」)を設計したいとしましょう。

さまざまな音声ファイル形式が存在します(基本的には拡張子で区別されます。例: .wav、:file:.aiff、:file:.au など)。そのため、異なる形式間で変換するための、増え続けるモジュール群が必要になります。

さらに、これらの音声データに対するさまざまな操作(ミキシング、エコーの追加、イコライザー機能の追加、人工ステレオ効果の作成など)があるため、これらの操作を処理するための、書ききれないほどのモジュール群も必要になります。

ここに、可能なパッケージ構造を示します(階層的なファイルシステム内):

sound/                          顶层包
      __init__.py               初始化 sound 包
      formats/                  文件格式转换子包
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  声音效果子包
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  filters 子包
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

パッケージをインポートするとき、Python は sys.path 内のディレクトリに基づいて、パッケージに含まれるサブディレクトリを探します。

ディレクトリは、__init__.py というファイルを含む場合にのみパッケージとして認識されます。これは主に、string のようなありふれた名前が、誤って検索パス内の有効なモジュールに影響を与えるのを防ぐためです。

最も単純な場合は、空の :file:__init__.py を置くだけです。もちろん、このファイルに初期化コードを含めたり、(後で紹介する)__all__ 変数に値を代入したりすることもできます。

ユーザーは、パッケージから特定のモジュールを一度に1つだけインポートできます。例:

import sound.effects.echo

これはサブモジュール sound.effects.echo をインポートします。フルネームでアクセスする必要があります:

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

サブモジュールをインポートするもう1つの方法は:

from sound.effects import echo

これもサブモジュール echo をインポートし、冗長なプレフィックスは不要なので、次のように使用できます:

echo.echofilter(input, output, delay=0.7, atten=4)

もう1つのバリエーションは、関数または変数を直接インポートすることです:

from sound.effects.echo import echofilter

同様に、この方法はサブモジュール echo をインポートし、その echofilter() 関数を直接使用できます:

echofilter(input, output, delay=0.7, atten=4)

注意してください。from package import itemこの形式を使用する場合、対応する item は、パッケージ内のサブモジュール(サブパッケージ)、またはパッケージ内で定義された関数、クラス、変数などの他の名前にすることができます。

import 構文はまず item をパッケージで定義された名前として扱い、見つからない場合は、モジュールとしてインポートしようとします。それでも見つからない場合は、:exc:ImportError例外が送出されます。

逆に、次のような形式をimport item.subitem.subsubitem使用する場合、最後の項目を除いてすべてパッケージでなければなりません。最後の項目はモジュールまたはパッケージにできますが、クラス、関数、変数の名前は指定できません。


パッケージから * をインポートする

もし私たちがfrom sound.effects import *を使用すると、何が起こるでしょうか?

Python はファイルシステムに入り、パッケージ内のすべてのサブモジュールを見つけ、それらを1つずつインポートします。

しかし、この方法は Windows プラットフォームではあまりうまく機能しません。Windows は大文字と小文字を区別しないシステムだからです。

Windows プラットフォームでは、ECHO.py というファイルが echo としてモジュールにインポートされるのか、Echo なのか、ECHO なのかを判断できません。

この問題を解決するには、正確なパッケージの索引を提供するだけで十分です。

インポート文は次の規則に従います。パッケージ定義ファイル __init__.pyには__all__という名前のリスト変数が存在する場合、from package import *を使用するとき、そのリスト内のすべての名前をパッケージの内容としてインポートします。

パッケージの作者は、パッケージを更新した後、__all__も更新することを忘れないでください。

次の例は file:sounds/effects/__init__.py に以下のコードを含んでいます:

__all__ = ["echo", "surround", "reverse"]

これは、from sound.effects import * という使い方をすると、パッケージ内のこれら3つのサブモジュールだけがインポートされることを意味します。

もし__all__が定義されていない場合は、from sound.effects import *この構文を使用する場合は、パッケージ sound.effects 内のサブモジュールは一切インポートされません。単にパッケージ sound.effects とその中で定義されたすべての内容をインポートするだけです(__init__.py で定義された初期化コードが実行される可能性があります)。

これにより、__init__.py 内で定義されたすべての名前がインポートされます。また、この文の前にインポートした明示的に指定されたモジュールを壊すことはありません。次のコードを見てください:

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

この例では、from...import を実行する前に、パッケージ sound.effects 内の echo モジュールと surround モジュールが現在の名前空間にインポートされています。(もちろん、__all__ を定義していれば問題ありません)

通常、私たちは*この方法でモジュールをインポートすることを推奨しません。この方法はコードの可読性を低下させることが多いためです。ただし、その分、入力の手間をかなり省くことができ、一部のモジュールは特定の方法でのみインポートできるように設計されています。

覚えておいてください、from Package import specific_submoduleこの方法を使用することは決して間違いではありません。実際、これが推奨される方法でもあります。ただし、インポートしようとするサブモジュールが他のパッケージのサブモジュールと名前が重複する可能性がある場合は別です。

構造内でパッケージがサブパッケージである場合(たとえば、この例ではパッケージ sound に対して)、兄弟パッケージ(同じレベルのパッケージ)をインポートしたい場合は、絶対パスを使用してインポートする必要があります。たとえば、モジュール sound.filters.vocoder がパッケージ sound.effects 内のモジュール echo を使用するには、from sound.effects import echo と書く必要があります。

from . import echo
from .. import formats
from ..filters import equalizer

暗黙的であれ明示的であれ、相対インポートは常に現在のモジュールから始まります。メインモジュールの名前は常に "__main__" です。Python アプリケーションのメインモジュールは、常に絶対パスで参照するようにしてください。

パッケージはさらに __path__ という属性を提供します。これはディレクトリのリストであり、含まれる各ディレクトリにはこのパッケージ用の __init__.py があります。この変数は、他の __init__.py が実行される前に定義する必要があります。この変数を変更することで、パッケージに含まれるモジュールやサブパッケージに影響を与えることができます。

この機能はあまり使われません。通常はパッケージ内のモジュールを拡張するために使用されます。

その他の拡張