TIL — Modules & Packages


Import Searchシーケンス


モジュール/packageが見つかった場合、Pythonは以下の順序で検索します.
  • sys.modules
  • built-in modules
  • sys.path
  • sys.モジュールはPythonがモジュールまたはパッケージを検索する最初のステップです.
    sys.モジュールは簡単な辞書です.また、インポートしたモジュールとパッケージを格納しています.
    これは、モジュールとパッケージをインポートすると、Pythonが再検索する必要がなくなることを保証することを意味します.
    したがって,新しくインポートしたモジュールはsysである.モジュールに見つかりません.
    build-inモジュールはPythonが提供するPython公式ライブラリです.
    Built-inモジュールはすでにPythonに含まれているので、Pythonは簡単に見つけることができます.
    sys.pathのデフォルトはlistで、string要素が含まれています.
    各string要素は、次のようにパスを表します.
    ['',
    '/Users/song-eun-u/anaconda3/bin',
    '/Users/song-eun-u/anaconda3/lib/python36.zip',
    '/Users/song-eun-u/anaconda3/lib/python3.6',
    '/Users/song-eun-u/anaconda3/lib/python3.6/lib-dynload',
    '/Users/song-eun-u/anaconda3/lib/python3.6/site-packages',
    '/Users/song-eun-u/anaconda3/lib/python3.6/site-packages/aeosa',
    '/Users/song-eun-u/anaconda3/lib/python3.6/site-packages/IPython/extensions',
    '/Users/song-eun-u/.ipython']
    したがって、Pythonはlistの各パスをチェックし、インポートするパッケージがそのパスにあることを確認します.
    まとめると、Pythonがインポートするモジュールとパッケージを見つけたとき、まずsysです.モジュールを確認し、ない場合はPython内蔵モジュールを確認し、最後にsysです.pathで指定したパスをチェックして検索します.
    sys.パスにも見つからない場合は、ModuleNotFoundErrorエラーを返します.
    Sysもインポートするモジュールですが、Pythonはどのようにsysモジュールの位置を見つけますか?
    import sys
    ...
    print(sys)
    ----出力結果----

    sysをインポートして出力すると、組み込みモジュールであることがわかります.これは、インストールする必要がなく使用できることを意味します.

    Absolute Path & Relative Path


    Pythonの内蔵モジュールとpipでインストールされている外部モジュールとパッケージは、通常、インポートに大きな影響を与えません.Built-inモジュールはもちろんよく探していますが、pipでインストールされた外務モジュールもsite-packagesというディレクトリに自動的にインストールされます.このsite-packagesはsysです.パスは既に含まれているので、検索に問題はありません.
    問題は直接開発したローカルパッケージです.独自に開発したローカルパッケージをインポートする場合は、パッケージの場所に基づいてインポートパスを正しく宣言する必要があります.Local packageをインポートするパスには、絶対パスと相対パスがあります.
    Absolute pathはその名の通り絶対パスです.絶対パスは、インポートされたファイルやパスにかかわらず、常に同じパスであるためです.
    通常、local packageをインポートする場合はabsolute pathを使用します.
    しかしabsolute pathを用いると,経路が長くなる可能性があるという欠点がある.
    従って、これらの欠点を補うために相対経路を用いることができる.
    Relative pathはabsolute pathとは異なり、プロジェクトのトップディレクトリではなくインポート場所に基づいてパスを定義します.したがって、通常、ローカルパケットに他のローカルパケットをインポートする際に相対パスが使用されます.
    相対インポートは、現在のモジュールの名前に基づいています.
    メインモジュールの名前は常にmainであるため、メインモジュールとして使用するモジュールは常に絶対インポートを使用する必要があります.
    Relative pathの利点は、宣言するパスの長さを減らすことですが、混同しやすく、ファイルの場所が変更された場合、パスの場所も変更する必要があります.したがって、一般的には絶対pathを使用することをお勧めします.

    init_.pyファイルの役割


    パッケージ内でinit.pyファイルがある場合は、パッケージのインポート時にinitします.pyファイルのコードが自動的に実行されます.ではinit.いったいpyファイルで何ができるの?
    通常、次のことができます.

    Import時のパスの全長を減らす


    import pkg.mod1
    pkg.mod1.func2()
    func 2関数を呼び出すたびに、すべてのパスを入力する必要があるため、面倒です.
    関数名をすぐに呼び出すことができれば、もっと便利かもしれません.幸いなことに、init.pyファイルで関数のパスを減らすことができます.方法は簡単です.init.まずpyファイルをインポートすればいいです
    # __init__.py
    from .mod1 import func2
    # main.py
    from pkg import func2
    func2()

    パッケージからインポートできる変数/関数/クラスの制限


    init.pyファイルを使用して、インポートできる変数/関数/クラスを制限できます.
    たとえば、モジュール内のすべての関数が外部に露出できない場合があります.パッケージの外部でこれらの関数をインポートおよび使用しないようにall変数を指定できます.
    パッケージでインポートできるすべての要素は、すべての変数で定義されます.
    all変数のデフォルト値は、すべての関数/変数/クラスです.
    したがって、all変数を個別に定義することで、インポート可能な要素を制限できます.
    all変数は文字列値要素を持つリスト(Stringsのlist of string)である.
    したがってstringを使用してlistにインポートする要素を宣言できます.

    他のパッケージのインポート時に最初に実行する必要があるコード。