Python-パッケージ、モジュールパス

9706 ワード

1. sys.モジュールとシステム.pathの違い
Pythonはimport時にsearch順を以下のように設定します.
  • sys.modules
  • built-in modules
  • sys.path
  • sys.モジュールは単純な辞書形式です.インポートされたモジュールやパッケージを格納している場所、新しくインポートされたモジュールなどが見つかりません.下記のコードを確認すれば確認できますが、まだまだたくさんあります.
    import sys 
    print(sys.modlues)
    >>>
    {'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module 'importlib._bootstrap' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>,
    '_weakref': <module '_weakref' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, 
    '_frozen_importlib_external': <module 'importlib._bootstrap_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'posix': <module 'posix' (built-in)>, 
    'encodings': <module 'encodings' from .... '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/rlcompleter.py'>, 
    'mod1': <module 'mod1' from '/Users/hoho/Google 드라이브/TIL/Documents/Python/mod1.py'>}
    build-inモジュールは、Pythonが提供するPython公式ライブラリを意味します.Pythonをインストールすると自動的に保存され、通常はlibフォルダに保存されます.
    sys.pathは基本的にlistのstring要素を有する.次のコードを見れば理解できます.
    import sys
    print(sys.path)
    >>>
    ['', '/Users/hoho/Google 드라이브/TIL/Documents/Python', 
    '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python37.zip', 
    '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7', 
    '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload', 
    '/Users/hoho/Library/Python/3.7/lib/python/site-packages', 
    '/usr/local/lib/python3.7/site-packages']
    sysとは何ですか.System-Pythonが提供する特定のパラメータと機能の略.オペレーティングシステムモジュールに存在し、Python Interpreter(エディタと理解)が提供する変数と関数を直接制御できます.既にインストールされているため、build-inモジュールに属します.
    私たちはすでに上で違いを見ましたがsys.モジュールはモジュールの集合、sysです.pathには経路の違いがあります.
    システム.modulesはdictの形式でsysです.pathにも違いがあり、リスト内のstringの形式があります.
    sys.pathはpip(Python Installerと理解)を使用して新しくインストールされたパッケージのパス(stie-package)を検索し、私が新しく作成したパッケージやモジュール(local package,local modules)もpathを登録することで設定します.
    偽書を検閲するシステム.pathのコードを見ると、1番インデックスは任意に登録されたpathであることがわかります.
    モジュールまたはパケットが上記順序modules => built-in => pathで見つからない場合、ModuleNotFoundErrorが発生する.
    2.Absolute pathとRelative pathの違い
    独自に開発したパッケージをインポートする場合は、パッケージの場所に基づいてインポートパスを正しく宣言し、パッケージのパスをインポートするには絶対パスと相対パスが必要です.絶対パスは絶対パスです.my appというプロジェクトがあると仮定します.
    └── my_app
        ├── main.py
        ├── package1
        │   ├── module1.py
        │	│	└── function1()
        │   └── module2.py
        └── package2
            ├── class 1
            ├── __init__.py
            ├── module3.py
            ├── module4.py
            └── subpackage1
                └── module5.py
                    └── function2()
    main.pyで絶対パスを使用する方法は、次のコードに示します.
    from package1 import module1
    from package1.module2 import function1
    from package2 import class1
    from package2.subpackage1.module5 import function2
    my appというプロジェクトの最上位レベルのpackage 1,2から始まることがわかります.
    上記のパスの最後のパスを使用すると、次のパスとして表示されます.
    my_app => package2 => subpackage1 => module5.py # 경로
    my_app/package2/subpackage1/module5.py # 리눅스의 directory 경로 형식
    my_app\package2\subpackage1\module5.py # 윈도우의 형식
    my_app.package2.subpackage1.module5.py # 파이썬에서는 slash나 back slash 대신 dot(.)을 사용해서 표현
    from package2.subpackage1.module5 import function2 # 위 dot으로 표현한 것을 파이썬에서 임폴트 할 때 쓰는 방법
    既にmy appという項目に入っているので、my appは省略します.項目を外したからといって可能だと思わないでください.
    すなわちmy appプロジェクトでは,どのファイル,どの場所からインポートしてもパスは常に上と同じであるため,絶対パスと呼ぶ.
    絶対パスの欠点は、パスが長くなる可能性があることです.これらの欠点を補うために、相対パスを使用することができる.
    相対パスは、絶対パスとは異なるimport位置に基づいてパスを定義します.したがって、相対パスは、通常、ローカルパケットから他のローカルパケットをインポートするために使用されます.
    package 2のmodule 3で、package 2のclass 1とpackage 2のサブpackage 1のmodule 5の関数2をインポートする場合は、次の操作を行います.
    # package2/module3.py
    
    from . import class1 # class1은 package2 에 있다.
    from .subpackage1.module5 import function2
    dot(.)import宣言ファイルの現在位置を指します.現在の位置はpackage 2/module 3です.したがって、必要なモジュールのパスを現在の位置から宣言するだけでよい.
    また、dotは2つ使用できます.2つのポイントは、現在の場所から親ディレクトリへの可能なパスです.
    # subpackage1/module5.py
    from ..module4 import class4
    相対パスの利点は、宣言するパスの長さを減らすことですが、混同しやすく、ファイルの場所が変更された場合、パスの場所も変更する必要があります.そのため、できるだけ絶対パスを使うことをお勧めします.
    これらはすべて、同じプロジェクト内にパッケージがあると仮定した場合に行われます.別のプロジェクトのパスから別の方法が必要です.syspathで指定:)それでいいです.
    3.mainモジュールパッケージのインポート方法
    main.pyが独自に設計したローカルパッケージを適用しようとimportを行い、以下のエラーが発生しました.
    参考までにadd and multiplyはmainです.pyの親ディレクトリに格納されます.
    from .add_and_multiply import add_and_multiply
    
    if __name__ == "__main__":
        print(add_and_multiply(1,2))
    >>>    
    importError: attempted relative import with no known parent package
    つまり、相対パスを使用すると、親パッケージがわかりません.どうしてこんなことが起こったのですか.簡単です.相対パスは、現在モジュールをロードするファイルの場所から始まります.つまりname=mainというファイルから始まります.親パッケージ(およびファイル)とサブパッケージ(およびファイル)を検索する場合、相対パスはmainです.pyから始まります.しかしmainとadd and multiplyモジュールは親と子供の関係ではなく、非常にレベルの高い関係です.つまり、Pythonが見つからないため、上記のエラーが発生します.
    では、どうすればいいのでしょうか.これも簡単です.絶対パスに変更すると、importは同じプロジェクト(ディレクトリ)に存在するため実行できます.
    from calculator.add_and_multiply import add_and_multiply
    #from .add_and_multiply import add_and_multiply
    
    if __name__ == "__main__":
        print(add_and_multiply(1,2))
    >>>
    /opt/homebrew/bin/python3 /Users/Barney/Desktop/repl/repl57.py
    /Users/Barney/Desktop/repl/repl57.py:1: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
      import imp
    5
    上記のパスを出力し、結果値の出力を支援します.
    絶対パスを使いたくなければ、相対パスも完全に可能だと思います.すぐに実行するmain.pyをインポートするプロジェクトの最上位レベルに移動すると、サブパスを参照して実行できますが、:)絶対パスを書きましょう.
    4. init.pyファイルの役割
    Initの目的は何ですか?このディレクトリがパッケージの一部であることをユーザに伝える役割を果たし,公開範囲を設定する役割も果たす.通常、initファイルは次のタスクを完了するのに役立ちます.
  • 導入時に減少する経路の全長
  • .
  • パッケージにインポート可能な変数/関数/クラス制限は
  • です.
  • 他のパケットのインポート時に最初に実行する必要があるコード
  • Initは、パッケージを実行するときに自動的に実行されるモジュールです.関数のinit関数と同じです.では、自動運転のモジュールにロードするモジュールを先に実行すれば、importタイピングを減らすことができます.簡単に言えば、次のコードのようです.
    #main.py
    from test.test1 import func2
    
    ->
    
    #__init__.py
    from test.test1 import func2
    
    #main.py
    func2()
    __init__.pyファイルに次のコードを設定すると、公開するモジュール、クラス、関数、変数などしか公開できません.すなわち,外部でimportを行う場合,利用可能なモジュールが設定される.
    __all__ = ["vietnam", "thailand"]
    含まれているモジュールはすべて公開できます.
    許可する変数、クラス、関数などは、initでそのモジュール(またはモジュール内の関数)などをImport後のallに予め指定しておくことができます.を選択します.pyは記入せず、名前しか記入できません.
    また、TILシリーズでは、モジュールやパッケージ、クラス、関数であまり理解されていない内容をまとめます.:)