[TIL]Python. Modules 2


モジュールとパッケージの検索方法


Import Searchシーケンス


abcというパッケージがあるとします
import abc
abcという名前のパッケージがインポートされました.Pythonはどこでこのかばんを探していますか?
Pythonは次の3つの場所を順番に表示して検索します
1. sys.modules
2. built-in modules
3. sys.path

1.sys.モジュール(ディクショナリとして構成)


Pythonモジュールまたはパッケージの最初のステーションを検索
Pythonには、インポートしたモジュールやパッケージを再検索する必要がないことを確認する機能があります.△とても便利です.
逆に、新しくインポートされていないモジュールはsysです.モジュールに見つからないことを意味します.
abcバッグは以前使ったことがありませんか?ではSY.モジュールにはありません!

2.built-in modules


Pythonが提供するPython公式ライブラリが含まれています.Built-inモジュールはすでにPythonに含まれているため、Pythonは簡単に見つけることができます.

3.sys.path(string要素付きlist)


最後に見たところがSYパスです
sys.pathのデフォルトはlistで、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はリスト内の各パスを1つずつチェックし、インポートするパッケージがそのパスにあることを確認します.
ちなみにsysはPythonに含まれるモジュールです.
したがってsysモジュールをインポートすることでsysを行う.モジュールとシステム.pathを出力または変更できます!
import sys

print(sys.path)
print(sys.modules)
sysモジュールの場所を見つけるにはどうすればいいですか?
sys.modulesはPythonがmoduleとpackageを探すために最初に見学した場所で、すでに内蔵されているので、moduleを内蔵している部分で見つけることができます.
'sys': <module 'sys' (built-in)>

整理する


インポートするモジュールとパッケージが見つかった場合、Pythonはまずsysを使用します.モジュールを確認し、ない場合はPython内蔵モジュールを確認し、最後にsysです.パスで指定したパスをチェックして検索します.
sys.パスにも見つからない場合は、ModuleNotFoundErrorエラーを返します.

Absolute Path & Relative Path


Pythonの内蔵モジュールとpipでインストールされる外部モジュールとパッケージは、通常、インポートにとって大きな問題ではありません.
問題は、直接開発されたローカルパッケージです.つまり、自分が開発したlocal packageをインポートする際には、packageの位置に基づいてimportパスを正しく宣言する必要があります.localpackageのパスの概念はAbsolulate/Relative

Absolute path(絶対パス)


Absolute pathは、インポートされたファイルまたはパスにかかわらず、常に同じパスを指します.絶対ファイルパスは、ファイルシステムのルートディレクトリから開始し、指定したファイルまたはディレクトリにアクセスする方法で、スラッシュまたはドライブラベルで表示されます. いいですよ. 
└── my_app
	├── main.py 
	├── package1 
	│ 	├── module1.py 
	│ 	└── module2.py 
	└── package2 
		├── --init--.py 
		├── module3.py 
		├── module4.py 
		└── subpackage1 
			└── module5.py
上記の例ではmy appというプロジェクトがあり、package 1とpackage 2というpackageが2つ、subpackage 2というネストされたpackageが1つあります.
Absolute pathを使用してpackage 1とpackage 2をインポートするとしたら?
from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1.module5 import function2
パスの開始点はすべてmy appプロジェクトの最上位ディレクトリから始まります.
サブパッケージ1のmodule 5モジュールのfunction 2関数をインポートするには、次のパスが必要です.
my_app => package2 => subpackage1 => module5.py
OS別に表示します.<리눅스> my_app/package2/subpackage1/module5.py<윈도우> my_app\package2\subpackage1\module5.py<Python> my_app.package2.subpackage1.module5.py(/ではなくパスを表す)
すでにmy appプロジェクトにあるのでmy appは省略され、結果は以下のように経路が表示されます
package2.subpackage1.module5.py
from package2.subpackage1.module5 import function2
my appプロジェクトでは、どのファイル、どの場所からインポートしてもパスは常に同じなのでabsolute path~と呼ばれます
現在のプロジェクトディレクトリはdefault losysであることに注意してください.pathに含まれます.したがって、absolute pathは現在のディレクトリからパスを開始します.通常、local packageをインポートする場合はabsolute pathを使用します.

欠点?


パスが長くなる可能性があります

Relative path


Absolute pathでは、セキュリティを保護するために経路が長いという欠点がある.
「absolute path:プロジェクトのトップディレクトリに基づいてパスを決定する」
->相対パスimportの位置に基づいてパスを定義します.
したがって、通常、相対パスを使用してlocalパケットから他のlocalパケットをインポートします.
└── my_app
	├── main.py 
	├── package1 
	│ 	├── module1.py 
	│ 	└── module2.py 
	└── package2 		#첫번째, class1을 import하겠다
		├── __init__.py 
		├── module3.py  #여기서
		├── module4.py 
		└── subpackage1 
				└── module5.py #두번째, 여기의 function2를 import하겠다
package 2のmodule 3では、package 2のclass 1とpackage 2のサブpackage 1のmodule 5のfunction 2関数をインポートするには、次の操作を行います.
# package2/module3.py
 from . import class1 
 from .subpackage1.module5 import function2
ここで、dot(.)は、importを宣言するファイルの現在の位置を表す.
現在の位置はpackage 2/module 3です.pyなので、現在の位置から必要なモジュールのパスを宣言するだけでいいです.dot 2개もあります.dot 2개(..)は、現在の場所から親ディレクトリへのパスとして使用されます.

欠点?


Relative pathの利点は、宣言するパスの長さを減らすことですが、混同しやすく、ファイルの場所が変更された場合、パスの場所も変更する必要があります.したがって,一般的には絶対pathを用いることを推奨する.

実戦練習


計算パッケージの作成

実際、私はこのような構造でノートパソコンでいくつかの仕事をしました.
1. main.pyがadd and multiplyを相対パスでインポートしたときに発生したエラーを確認し、次のPython公式ドキュメントを参照して、メインモジュールにパッケージ内のモジュールをインポートする方法を記録してください.
リンクテキスト
add and multiplyを相対パスとしてインポートします.
ImportError:importに対して相対しようとしたときにno nown parent packageというエラーが発生しました
from .calculator.add_and_multiply import add_and_multiply

if __name__ == '__main__':
    print(add_and_multiply(1,2))
    print(__name__)
    print("ok")
以上の場合はmainです.pyにインポートしますが、計算機ファイル構造ではmainはパッケージ内のファイルではありません.mainモジュールの名前は常に「main」であるため、Pythonアプリケーションモジュールとして使用するモジュールは常に絶対インポートを使用しなければならないというルールがあります.
->main.pyから相対パスを導入した以上、もちろんだめです!絶対パスに変換
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)
print(add_and_multiply(2,5))
<相対パスを使用できない理由>
上記で作成した例は、同じパッケージではありませんが、プロジェクトにあります.だからmain相対パスからpyにアクセスしてインポートできません.
私が実行しているファイルはadd and multiplyです.pyです.
計算機フォルダで乗算します.pyも一緒です.
同じ親計算機に含まれているため、絶対パスとして処理しても問題は発生しません.