Python3モジュール


前の章では、Python インタープリターを使用してスクリプトをプログラムしました。Python インタープリターを終了してから再度開始すると、定義したすべてのメソッドと変数が消えます。

この目的のために、Python は、一部のスクリプトまたは対話型インタープリター インスタンスで使用できるように、これらの定義をファイルに保存する方法を提供します。このファイルはモジュールと呼ばれます。

モジュールは、定義したすべての関数と変数を含むファイルであり、その拡張子は .py です。モジュールを他のプログラムでインポートして、モジュール内の関数などを使用することができます。これも Python 標準ライブラリを使用して行われます。

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

#!/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.py ファイルコードは:

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

def print_func( par ):
    print ("Hello : ", par)
    return

test.py サポートモジュールを導入します:

#!/usr/bin/python3
# Filename: test.py
 
# 导入模块
import support
 
# 现在可以调用模块里包含的函数了
support.print_func("php")

の出力結果上記の例:

$ python3 test.py 
Hello :  php

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

import ステートメントを使用するとき、Python インタープリターは対応するファイルをどのように見つけますか?

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

これは環境変数によく似ていますが、実際には、環境変数を定義することで検索パスも決定できます。

検索パスは Python がコンパイルまたはインストールされるときに決定され、新しいライブラリをインストールするときにも変更する必要があります。検索パスは、sys モジュールのパス変数に保存されます。簡単な実験を行うには、対話型インタープリターで次のコードを入力します。

>>> 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 ステートメントを使用すると、次のことが可能になります。 to import from モジュールの指定された部分を現在の名前空間にインポートするには、構文は次のとおりです:

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

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

from fibo import fib

このステートメントは使用しません。 fib モジュール全体を現在の名前空間にインポートすると、この宣言を実行するモジュールのグローバル シンボル テーブルに fib 内の 1 つのフィボナッチのみが導入されます。



From...import* ステートメント

次の宣言を使用するだけで、モジュールのすべてのコンテンツを現在の名前空間にインポートすることもできます:

from modname import *

これは、モジュールすべてのプロジェクトをインポートする簡単な方法を提供します。 。ただし、このステートメントは乱用すべきではありません。


モジュールの詳細

モジュールにはメソッド定義に加えて、実行可能コードも含めることができます。これらのコードは通常、このモジュールを初期化するために使用されます。このコードは、最初にインポートされたときにのみ実行されます。

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

そのため、モジュール作成者は、他のユーザーのグローバル変数をいじることを心配することなく、モジュール内でこれらのグローバル変数を安全に使用できます。

一方、何をしているのかを本当に理解している場合は、modname.itemname のような表記を通じてモジュール内の関数にアクセスすることもできます。

モジュールは他のモジュールをインポートできます。もちろん、モジュール (またはスクリプトなど) の先頭で import を使用してモジュールをインポートすることは、単なる慣例であり、必須ではありません。インポートされたモジュールの名前は、現在動作しているモジュールのシンボル テーブルに配置されます。

インポートを使用して、モジュール内の(関数と変数の)名前を現在の操作モジュールに直接インポートする方法もあります。例:

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

このインポート メソッドは、インポートされたモジュールの名前を現在の文字テーブルに置きません (したがって、この例では、名前 fibo は定義されていません)。

モジュール内のすべての (関数、変数) 名を現在のモジュールの文字テーブルに一度にインポートする方法もあります:

>>> 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__ 属性があり、その値が '__main__' の場合はモジュール自体が実行中であることを示し、それ以外の場合はインポートされます。


dir() 関数

内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回:
</p>
<pre>
>>> 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 ライブラリ リファレンス ドキュメント (つまり、後の「ライブラリ リファレンス ドキュメント」) で紹介されています。

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

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

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

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>

Package

Package は、「ドット モジュール名」を使用して 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 というファイルが含まれている場合にのみパッケージとして認識されます。これは主に、決まりきった名前 (文字列など) が検索パス内の有効なモジュールに誤って影響を与えるのを避けるためです。

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

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

import sound.effects.echo

これはサブモジュール mod:song.Effects.echo をインポートします。 アクセスするにはフルネームを使用する必要があります:

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

サブモジュールをインポートする方法もあります:

from sound.effects import echo

これはサブモジュール mod:echo もインポートします。そして、そのような長い接頭辞は必要ないので、次のように使用できます:

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

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

from sound.effects.echo import echofilter

同様に、これはこのメソッドはサブモジュール :mod:echo をインポートし、その :func:echofilter 関数を直接使用できます:

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

パッケージインポートアイテムから使用する場合はこれに注意してくださいフォームでは、対応する項目は、パッケージ内のサブモジュール (サブパッケージ)、またはパッケージ内で定義されている関数、クラス、変数などの他の名前にすることができます。

インポート構文は、最初に項目をパッケージ定義の名前として扱います。見つからない場合は、モジュールとしてインポートしようとします。まだ見つかっていない場合は、おめでとうございます。:exc:ImportError 例外がスローされました。

逆に、import item.subitem.subsubitem のようなインポートフォームを使用する場合、最後の項目を除くすべてがパッケージである必要があり、最後の項目はモジュールまたはパッケージにすることができますが、クラスにすることはできません、関数または変数名。


Import * from a package

from sound.Effects import * を使用するとどうなるかを想像してみてください。

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

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

このタイプのプラットフォームでは、ECHO.py というファイルが module: mod:echo または: mod:Echo または mod:ECHO としてインポートされることをあえて保証する人は誰もいません。

(たとえば、Windows 95 では各ファイルの最初の文字が大文字で表示されるので迷惑です)、DOS の 8+3 命名規則は長いモジュール名を処理するため、問題はさらに複雑になります。

この問題を解決するには、パッケージ作成者に正確なパッケージ インデックスを提供するよう依頼するしかありません。

Import ステートメントは次のルールに従います: パッケージ定義ファイル __init__.py に __all__ というリスト変数がある場合、 from package import * を使用すると、このリスト内のすべての名前がパッケージ コンテンツとしてインポートされます。


パッケージの作成者として、パッケージの更新後に __all__ も更新されていることを忘れないでください。あなたは、私はこれをしない、import* は使用しない、と言ったでしょう、わかりました、問題ありません、誰があなたを上司にするのですか。これは例です。file:sounds/Effects/__init__.py には次のコードが含まれています:


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

これは、from sound.Effects import * を使用する場合、これをパッケージ内でのみインポートすることを意味します。 3 つのサブモジュール。

__all__ が true であるが定義されていない場合、sound.Effects import * の構文を使用すると、package:mod:sound.Effects 内のサブモジュールは *インポートされません*。パッケージ :mod:sound.Effects とその中で定義されているすべてのものをインポートするだけです (おそらく :file:__init__.py で定義された初期化コードを実行します)。

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

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

この例では、from...import を実行する前に、package:mod:sound.Effects 内のエコー モジュールとサラウンド モジュールが現在の名前空間にインポートされます。 (もちろん、__all__ が定義されていれば問題ありません)

通常、* このメソッドを使用してモジュールをインポートすることは推奨しません。このメソッドはコードの可読性の低下につながることが多いためです。ただし、これにより多くのキーストロークが節約され、一部のモジュールは特定の方法でのみインポートされるように設計されています。

from Package import specific_submodule を使用しても何も問題がないことを覚えておいてください。実際、これは推奨されるアプローチです。ただし、インポートするサブモジュールが別のパッケージのサブモジュールと同じ名前を持つ可能性がある場合は除きます。

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

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

暗黙的または明示的な相対インポートが現在のモジュールから開始されるかどうか。メイン モジュールの名前は常に「__main__」です。Python アプリケーションのメイン モジュールは常に絶対パスを使用して参照する必要があります。

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

この関数は一般的には使用されず、通常はパッケージ内のモジュールを拡張するために使用されます。