[TIL] Modules & Packages


Modules


Module
  • 変数、関数、クラスを含むファイル
  • 他のファイルで再利用可能
  • 長いコードを複数のファイルに分割して整理するために使用されます!
  • 例えば、私たちが使用しているlen()関数はモジュールとして実装されており、私たちは使用することができます!
    モジュールは既製でもいいし、自分で作ってもいいです.
    ## my_module.py
    my_module_var = 7
    
    
    def my_module_func():
        return "Hello!"
    
    
    class MyModuleClass:
        pass
    👆🏻 一般的なファイルを作成し、コードを保存した後
    このモジュールを別のファイルからインポートすると使用できます.
    <모듈 이름>.<모듈에서 사용하길 원하는 변수/함수/클래스 이름>
    import my_module
    どのファイル、どのクラスの関数または変数を書き込むか分かりません.
    モジュールの前に名前を付ける必要があります(namespace structure!)
    👇🏻 モジュールの構造と作業順序!

    モジュールのインポート方法!
    1.importキーのみ使用
    2. import from
    from <모듈 이름> import <함수/변수/클래스1>, <함수/변수/클래스2>, ..., <함수/변수/클래스N>
    -
    from my_module import my_module_func, my_module_var
    print(my_module_var)
    my_module_func()
    :モジュールで明示的に使用する場合に使用します.
    (ただしlocalscopeを持つ変数と名前の競合は推奨されません)
    3. import as
    from my_module  import my_func as f1
    from my_module2 import my_func as f2
    from my_module3 import function_with_name_too_long as f3
    -
    f1()
    f2()
    f3()
    :インポートモジュールの要素を必要な名前として使用します.
    import my_module as m1
    -
    m1.my_module_func()
    :モジュール名を指定することもできます.

    Packages

  • モジュールと同様に、他のファイルから読み込んで使用
    (より大きく複雑なコードではなく)
  • 1つのモジュールのコードが長すぎる場合は、複数のファイルのコードを
    他の場所からモジュールにロードして使用します!

    👆🏻 Pythonファイルからなるディレクトリがパッケージになります
    (ディレクトリ名=>package名)
  • Module importの場合、必要なパッケージのモジュール
  • をインポートできます.
    import pkg.mod1
    from pkg.mod2 import func2
    
    
    pkg.mod1.func2()
    func2()
  • __init__.pyパッケージを使用する場合は、ファイルを使用して初期設定
  • を行うことができます.
    # __init__.py
    from .mod1 import func2
    
    
    # main.py
    from pkg import func2
    
    func2()
    👆🏻 これにより、関数名を直接呼び出すことができます.
  • __all__:packageでインポートできるすべての要素を定義
    :この変数を使用すると、パッケージの外部インポート時に使用されないようにします.
    :default値は、すべての関数/変数/クラスです.
    個別に定義すると、これらの要素をインポートできないように制限します!
  • # __init__.py
    from .mod1 import func2
    from .mod2 import func3
    
    __all__ = ['func2', 'func3']
    
    
    # main.py
    from pkg import *
    
    func2()
    func3()
    func4() ## <== Error. func4 함수는 __all__ 에 정의되지 않았으므로 import 될 수 없음.
    👆🏻 String値の要素リスト.
    インポートする要素をstringでlistに宣言すればいいです.

    How Import Statement Finds Modules & Packages


    では、Pythonはどのようにモジュールとパッケージをインポートしますか?
    どうやって検索しますか?
    import abc
    👆🏻 yorokeimport、しかしPythonはどのようにモジュール/packageを探しますかを知りません
    どんな原理で探しますか?

    1) 3steps to find module/package

  • sys.modules
  • built-in modules
  • sys.path
  • sys.modules


    Pythonが最初に確認した場所!
  • simpledictionary
  • sys.一度保存したモジュールをmodulesで再検索することなく特定できます!
  • したがって、新しく導入されたモジュールはsysである.モジュールで見つかった数X
  • built-in modules

  • Python提供のPython公式ライブラリ!
  • Built-inモジュールは既にPythonに含まれている.
    見つけやすい
  • sys.path

  • 最終局
  • sys.pathはstring要素のlist形式
  • ['',
     '/Users/song-eun-u/anaconda3/bin',
     '/Users/song-eun-u/anaconda3/lib/python36.zip',
     '/Users/song-eun-u/anaconda3/lib/python3.6']
    👉🏻 Pythonはリストのパスを1つずつチェックし、そのパスにインポートする要素があるかどうかを決定します.
  • sysはPythonに含まれるモジュールである.
    sysモジュールsysをインポートします.modules, sys.pathを出力、変更できます.(👇🏻 Yoroche!)
  • import sys
    -
    print(sys.path)
    print(sys.modules)
    Pythonは、この3つのステップでインポートするモジュールとパッケージを決定します.
    見つからない場合はModuleNotFoundErrorに戻ります

    2) Absolute path & Relative path


    内蔵モジュールとpipでインストールされたすべての外部ビューモジュール
    最初の3段階で見つけることができますが.
    自社開発のlocal packageをインポートする場合は、場所に応じてパスを正しく宣言します.
    └── my_app
        ├── main.py
        ├── package1
        │   ├── module1.py
        │   └── module2.py
        └── package2
            ├── __init__.py
            ├── module3.py
            ├── module4.py
            └── subpackage1
                └── module5.py
    👆🏻 プロジェクト構造を次のように仮定します.

    Absolute path:絶対パス

  • インポートされたファイルは、パスに関係なく常に同じ
  • from package1 import module1
    from package1.module2 import function1
    from package2 import class1
    from package2.subpackage1.module5 import function2
  • 経路の起点はすべてプロジェクトの最上位プロジェクトmy appから来ている.
  • Linuxはスラッシュ(/)、ウィンドウは反スラッシュ()、Pythonはdot(.)タグを使用
  • リレーショナルパスリレーショナルパス:相対パスそうたいぱす

  • インポート位置に基づいてパスを定義
  • localpackage他のlocalpackage
  • をインポートするために使用
    # package2/module3.py
    -
    from . import class1
    from .subpackage1.module5 import function2
    -
    # subpackage1/module5.py
    from ..module4 import class4
  • dot . 1つは、宣言ファイルの現在の場所です.
    dot .. 両方のパスは、現在の場所から親ディレクトリへのパス
  • Relative pathはAbsolute pathと比較して経路長が短いが混同しやすい.
    欠点は、ファイルの場所が変更された場合、パスの場所を変更する必要があることです.

    3)練習-計算パッケージの作成


    プロジェクトの作成

  • init.pyファイルにはコードはありませんが、initファイルはディレクトリがパッケージであることを通知する役割を果たします.

    👇🏻 main.py
  • # absoulte path
    #from calculator.add_and_multiply import add_and_multiply 
    -
    # relative path
    from .calculator.add_and_multiply import add_and_multiply
    -
    if __name__ == '__main__':
        print(add_and_multiply(1,2))
    👇🏻 add_and_multiply.py
    from .multiplication import multiply
    # from calculator.multiplication import multiply
    def add_and_multiply(a,b):
        return multiply(a,b) + (a+b)
    👇🏻 multiplication.py
    def multiply(a,b):
        return(a*b)
  • main.pyからadd and multiplyを相対パスにインポートしたときに発生したエラーを確認します
  • 以下のPython公式ドキュメントを参照して、mainモジュールにパッケージ内のモジュールのインポート方法を記録してください.
    Python公式ドキュメント

  • ある人は“no par母package”と言います
    相対経路なので、このような問題が発生します...
    公式文書を参考に調べてみました.pyファイルには独自のルールがありますか?

    👆🏻 mainモジュールの名前はいつも__main__.pyと言って、それにファイル名を変えて、少しも影響していませんて、ファイル名は変えて、同じ間違いが現れました
    いずれにしても、相対経路自体が問題だと思いますが...

    👆🏻 もとは正式な書類の最後の部分で、mainmoduleは親切に私に教えてくれて、必ず絶対パスを使います.もしもし、あなたも知らないハラン.
    main.pyファイルからパケットの前の相対パスタグが削除されました.
    今からちゃんと帰れ!
  • add_and_multiply.pyに複数の関数の絶対パスと相対パスをそれぞれインポートし、メインモジュールとの違いを考慮して結果を出力します.

  • 👆🏻 まず相対パスでインポートすると、エラーが発生します.

    👆🏻 No nown parent packageはパッケージ名を指定しますが、importは含まれません.

    👆🏻 絶対パスでパッケージ名を指定してもエラー!モジュールがありません!!
    どうしたんですか.

    👆🏻 絶対パスは現在のディレクトリから始まりますが、必ずしも最上位ディレクトリから始まるわけではありません.
    スクリプトが属するパスからdefaultとして指定された現在のディレクトリを決定できます.
    私の場合、絶対パスの起点はcalculator packageディレクトリなので、それ以外の絶対パスに指定すると正常に動作します!