Python 模塊(Module)調用


2021-01-27

首先我們需要了解一下基礎:

參考我的博客:https://www.cnblogs.com/zhangchao0515/p/14333370.html

接下來,我們講的重點是 Python 模塊(Module)調用

主要有以下5種方法:
1. python默認的模塊導入執行過程--
  1) 要么是同一目錄下,可以相互調用
  2) 要么是在子目錄下,可以從當前模塊往下
    (都是需要__init__.py,而且是根據python自己的機制)
  針對1)和2)是默認的機制-- python會自動將該文件的的路徑臨時添加到環境變量中,類似在文件中 sys.path.append('當前py文件目錄')

2. 要么在當前的py文件中將項目根目錄加入 -- 作用域是當前py文件
  sys.path.append('項目根目錄')

3. 先在cmd中設置環境變量,作用域是當前的cmd窗口   -- pycharm 就是類似這種效果,可以測試一下
  1) set PYTHONPATH=D:\Projects\python\vscode\python-module
    可以通過命令查看:echo %PYTHONPATH%
  2)執行文件
    python xxx.py

4. 設置全局變量 -- 作用域是一直存在
  PYTHONPATH=D:\Projects\python\vscode\python-module
 
5. 把文件添加到默認路徑中 -- 還是算了吧,一般都不用這種的。除非是針對python的封裝等,比如Anaconda等。
 

一、我們先創建一個測試項目python-module

1、搜索路徑

當你導入一個模塊,Python 解析器對模塊位置的搜索順序是:

  • 1、當前目錄
  • 2、如果不在當前目錄,Python 則搜索在 shell 變量 PYTHONPATH 下的每個目錄。
  • 3、如果都找不到,Python會察看默認路徑。UNIX下,默認路徑一般為/usr/local/lib/python/。

模塊搜索路徑存儲在 system 模塊的 sys.path 變量中。變量里包含當前目錄,PYTHONPATH和由安裝過程決定的默認目錄。

2、Python中的包

包是一個分層次的文件目錄結構,它定義了一個由模塊及子包,和子包下的子包等組成的 Python 的應用環境。

簡單來說,包就是文件夾,但該文件夾下必須存在 __init__.py 文件, 該文件的內容可以為空。__init__.py 用於標識當前文件夾是一個包。

3、目錄結構如下

目錄是D:\Projects\python\vscode\python-module

python-module
  src
    main
      package1
        __init__.py
        module1.py
      package2
        package3
          __init__.py
          module2.py
        __init__.py
        module2.py
        moduletest1.py
        moduletest2.py
        moduletest3.py
        moduletest4.py
    test

 

4、文件說明

1) 首先我們創建目錄 python-module\src\main和python-module\src\test
2) 然后在python-module\src\main創建包
比如python-module\src\main\package1,python-module\src\main\package1\__init__.py
python-module\src\main\package2, python-module\src\main\package2\__init__.py
python-module\src\main\package2\package3, python-module\src\main\package2\package3\__init__.py
3) 創建py文件
python-module\src\main\package1\module1.py
python-module\src\main\package2\module2.py
python-module\src\main\package2\moduletest1.py
python-module\src\main\package2\moduletest2.py
python-module\src\main\package2\moduletest3.py
python-module\src\main\package2\moduletest4.py
python-module\src\main\package2\package3\module3.py
4) 文件簡要說明
module1.py module2.py module3.py是我們的待測試代碼
moduletest1.py moduletest2.py moduletest3.py moduletest4.py是針對四種場景的測試代碼
5)代碼
module1.py 如下所示:
def fun1():
  print ("我是來自 module1")

module2.py 如下所示:

def fun2():
  print ("我是來自 module2")

module3.py 如下所示:

def fun3():
  print ("我是來自 module3")

5、執行方法

1)打開cmd 

2)切換到要執行的py目錄下

3)執行py

例如:

python moduletest1.py

 

一、python默認的模塊導入執行過程

我們知道了搜索路徑,我們直接考慮第一種搜索:

當你導入一個模塊,Python 解析器對模塊位置的搜索順序是:

  • 1、當前目錄
  • 2、如果不在當前目錄,Python 則搜索在 shell 變量 PYTHONPATH 下的每個目錄。
  • 3、如果都找不到,Python會察看默認路徑。UNIX下,默認路徑一般為/usr/local/lib/python/。

模塊搜索路徑存儲在 system 模塊的 sys.path 變量中。變量里包含當前目錄,PYTHONPATH和由安裝過程決定的默認目錄。

會先搜索當前目錄,其實就是把當前目錄臨時添加到環境變量,作用域僅限於該py文件。由此引入了方法1

1. python默認的模塊導入執行過程--
  1) 要么是同一目錄下,可以相互調用
  2) 要么是在子目錄下,可以從當前模塊往下
    (都是需要__init__.py,而且是根據python自己的機制)
  針對1)和2)是默認的機制-- python會自動將該文件的的路徑臨時添加到環境變量中,類似在文件中 sys.path.append('當前py文件目錄')

1、首先我們先打印一下 sys.path看一下環境

moduletest1.py如下

import sys
# 測試第一種:使用python默認的模塊導入機制
# 只能導入同一目錄或子目錄下的模塊,效果類似 sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
# python moduletest1.py -- 作用域只是當前的python


if __name__ == '__main__':
  print(sys.path)

打開cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

 我們可以看到,默認就會把該目錄添加到環境變量中。

2、我們直接引入模塊module2.py和module3.py

moduletest1.py如下

import sys
# 測試第一種:使用python默認的模塊導入機制
# 只能導入同一目錄或子目錄下的模塊,效果類似 sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
# python moduletest1.py -- 作用域只是當前的python

# 1. 這個是在同一目錄下,可以相互調用。效果類似在該文件中添加 sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
from module2 import fun2
# 2. 這個是在子目錄下,只能自己調用子目錄的,反過來不行。效果類似在該文件中添加 sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
from package3.module3 import fun3
# 3. 會報錯,不識別模塊package1
# from package1.module1 import fun1

if __name__ == '__main__':
  print(sys.path)
  fun2()
  fun3()
  # fun1()

打開cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

 這是因為:搜索路徑,會先搜索當前目錄

3、我們再引入模塊module1.py

moduletest1.py如下
import sys
# 測試第一種:使用python默認的模塊導入機制
# 只能導入同一目錄或子目錄下的模塊,效果類似 sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
# python moduletest1.py -- 作用域只是當前的python

# 1. 這個是在同一目錄下,可以相互調用。效果類似在該文件中添加 sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
from module2 import fun2
# 2. 這個是在子目錄下,只能自己調用子目錄的,反過來不行。效果類似在該文件中添加 sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
from package3.module3 import fun3
# 3. 會報錯,不識別模塊package1
from package1.module1 import fun1

if __name__ == '__main__':
  print(sys.path)
  fun2()
  fun3()
  fun1()

打開cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

 那是因為他不會往上級目錄搜索

二、通過sys.path.append 或者sys.path.exclude臨時導入環境變量

當你導入一個模塊,Python 解析器對模塊位置的搜索順序是:

  • 1、當前目錄
  • 2、如果不在當前目錄,Python 則搜索在 shell 變量 PYTHONPATH 下的每個目錄。
  • 3、如果都找不到,Python會察看默認路徑。UNIX下,默認路徑一般為/usr/local/lib/python/。

模塊搜索路徑存儲在 system 模塊的 sys.path 變量中。變量里包含當前目錄,PYTHONPATH和由安裝過程決定的默認目錄。

 

通過sys.path.append 或者sys.path.exclude臨時導入環境變量,它的作用域也只是該py文件。

1、按照慣例先看一下sys.path

moduletest2.py如下

import sys
# 測試第二種:
# 在文件中添加 sys.path.append('項目根目錄'), sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
# python moduletest2.py -- 作用域只是當前的python
if __name__ == '__main__': print(sys.path)

打開cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

 2、我們直接引入模塊module1.py和module2.py和module3.py

moduletest2.py如下

import sys
import os
# 測試第二種:
# 在文件中添加 sys.path.append('項目根目錄'), sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
# python moduletest2.py -- 作用域只是當前的python
# 獲取當前文件的目錄
# curpath = os.path.abspath(os.path.dirname(__file__))
# 獲取項目根目錄 D:\\Projects\\python\\vscode\\python-module
projectpath = os.path.abspath(os.path.dirname(__file__)+r'../../../')

# 1. 在該文件中添加 sys.path.append('項目根目錄') -- 作用域只是當前py文件
sys.path.append(projectpath)

from src.main.package2.module2 import fun2
# 2. 在該文件中添加 sys.path.append('當前文件所在的目錄') ,python默認會把該目錄加入,不需要這步操作 -- 作用域只是當前py文件
# sys.path.append(curpath)
# from module2 import fun2
from src.main.package2.package3.module3 import fun3
from src.main.package1.module1 import fun1


if __name__ == '__main__':
  print(sys.path)
  fun2()
  fun3()
  fun1()

打開cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

 所以,環境變量里面一個是自動添加的目錄,一個是我們自己添加的目錄,兩個同樣的作用域是該py文件。且都是臨時的。

自動添加的:'D:\\Projects\\python\\vscode\\python-module\\src\\main\\package2'
我們添加的:'D:\\Projects\\python\\vscode\\python-module'

由此我們可以添加'D:\\Projects\\python\\vscode\\python-module'目錄下的模塊,需要引入相關包。該方法不能動源碼結構,否則要大量修改源碼。

當然我們的包名引入還可以用一的,因為也存在 'D:\\Projects\\python\\vscode\\python-module\\src\\main\\package2'。

3、混用這兩個路徑

moduletest2_1.py如下

import sys
import os
# 測試第二種:
# 在文件中添加 sys.path.append('項目根目錄'), sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
# python moduletest2_1.py -- 作用域只是當前的python
# 獲取當前文件的目錄
# curpath = os.path.abspath(os.path.dirname(__file__))
# 獲取項目根目錄 D:\\Projects\\python\\vscode\\python-module
projectpath = os.path.abspath(os.path.dirname(__file__)+r'../../../')

# 1. 在該文件中添加 sys.path.append('項目根目錄') -- 作用域只是當前py文件
sys.path.append(projectpath)

# 很明顯用這個路徑'D:\\Projects\\python\\vscode\\python-module\\src\\main\\package2'
from module2 import fun2
from package3.module3 import fun3
# 很明顯用這個路徑 D:\\Projects\\python\\vscode\\python-module
from src.main.package1.module1 import fun1


if __name__ == '__main__':
  print(sys.path)
  fun2()
  fun3()
  fun1()

打開cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

真會玩!!!

4、我們再引入模塊module1.py和module2.py和module3.py

moduletest2_2.py如下

import sys
import os
# 測試第二種:
# 在文件中添加 sys.path.append('項目根目錄'), sys.path.append('當前文件所在的目錄') -- 作用域只是當前py文件
# python moduletest2_2.py -- 作用域只是當前的python
# 獲取當前文件的目錄
# curpath = os.path.abspath(os.path.dirname(__file__))
# 獲取項目的main目錄 D:\\Projects\\python\\vscode\\python-module\\src\\main
mainpath = os.path.abspath(os.path.dirname(__file__)+r'../')

# 1. 在該文件中添加 sys.path.append('項目根main目錄') -- 作用域只是當前py文件
sys.path.append(mainpath)

from package2.module2 import fun2
from package2.package3.module3 import fun3
from package1.module1 import fun1


if __name__ == '__main__':
  print(sys.path)
  fun2()
  fun3()
  fun1()

打開cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

是不是類似java的包,好會玩,快被玩壞了!!!

 

三、在命令窗口設置 PYTHONPATH

當你導入一個模塊,Python 解析器對模塊位置的搜索順序是:

  • 1、當前目錄
  • 2、如果不在當前目錄,Python 則搜索在 shell 變量 PYTHONPATH 下的每個目錄。
  • 3、如果都找不到,Python會察看默認路徑。UNIX下,默認路徑一般為/usr/local/lib/python/。

模塊搜索路徑存儲在 system 模塊的 sys.path 變量中。變量里包含當前目錄,PYTHONPATH和由安裝過程決定的默認目錄。

這里我們就用到第2種搜索

1、按照慣例,先看一下sys.path

moduletest3.py如下

import sys


if __name__ == '__main__':
  print(sys.path)

打開cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

2、在命令行設置PYTHONPATH -- 作用域是該窗口,只要窗口不關閉,在窗口中執行就行

moduletest3.py如下

import sys


if __name__ == '__main__': print(sys.path)

打開cmd,執行

set PYTHONPATH=D:\Projects\python\vscode\python-module
echo %PYTHONPATH%

結果如下所示:

 切換到該文件所在目錄,再次執行 

python moduletest1.py

結果如下所示:

 在該環境變量中:

自動添加的:'D:\\Projects\\python\\vscode\\python-module\\src\\main\\package2'
我們添加的:'D:\\Projects\\python\\vscode\\python-module'

由此我們可以添加'D:\\Projects\\python\\vscode\\python-module'目錄下的模塊,需要引入相關包。

這里的作用域是該窗口。

3、引入模塊module1.py和module2.py和module3.py

moduletest3.py如下

import sys
# 測試第三種:在cmd中切換到該目錄下,執行 set PYTHONPATH=D:\\Projects\\python\\vscode\\python-module
# 我們可以查看 echo %PYTHONPATH%
# 作用域是該cmd窗口,這要窗口下執行,都是有該環境變量存在
# python moduletest3.py


from src.main.package2.module2 import fun2
from src.main.package2.package3.module3 import fun3
from src.main.package1.module1 import fun1


if __name__ == '__main__':
  print(sys.path)
  fun2()
  fun3()
  fun1()

在剛才窗口中執行 

python moduletest1.py

結果如下所示:

如果窗口沒有設置 PYTHONPATH,肯定會報錯。

什么?你不信!!!

那我們就測試一下

重新打開一個窗口或者在該窗口執行以下操作:

set PYTHONPATH=

結果如下:

在剛才窗口中執行 

python moduletest1.py

結果如下所示:

我就說嘛,請不要抬杠!!!

4、如果是在pycharm中,則不會報錯,不需要在命令行設置PYTHONPATH,因為pycharm已經設置好了

注意!!!好玩的又來了。

有些會問,我沒有設置PYTHONPATH,為什么在pycharm沒有報錯,那是因為pycharm已經設置好了。

pycharm就是采用類似這種的策略。

1)我們打開pycharm,導入該項目,看一下

打開 File --> Settings --> Build,Execution,Deployment --> Console --> Python Console

 我們看一下啟動腳本 Starting script

import sys; print('Python %s on %s' % (sys.version, sys.platform))
sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])

好家伙!!!

啟動腳本肯定是先執行的。 -- 至於如何設計,不太清楚,你們研究好了可以告訴我一聲,我謝謝啊。

(1) 這里面先引入 import sys;

(2) 之后調用print('Python %s on %s' % (sys.version, sys.platform))打印信息,

我的打印結果是

 也就是說

sys.version: 3.8.3 (default, Jul  2 2020, 17:30:36) [MSC v.1916 64 bit (AMD64)]
sys.platform: win32

(3) 然后是 sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS]),把目錄添加到環境變量中,

至於WORKING_DIR_AND_PYTHON_PATHS是識別不了的,pycharm肯定在其他地方定義了。

不過幸虧這名字取得我們能看懂意思,就是就是工作目錄和python目錄。

這里的工作目錄一看就是項目目錄。我們可以驗證一下。

2)我們已經把項目導入了pycharm,我們執行 moduletest3.py 試試看

當然我們這里什么都沒設置

moduletest3.py如下:-- 和之前一樣

import sys
# 測試第三種:在cmd中切換到該目錄下,執行 set PYTHONPATH=D:\\Projects\\python\\vscode\\python-module
# 我們可以查看 echo %PYTHONPATH%
# 作用域是該cmd窗口,這要窗口下執行,都是有該環境變量存在
# python moduletest3.py


from src.main.package2.module2 import fun2
from src.main.package2.package3.module3 import fun3
from src.main.package1.module1 import fun1


if __name__ == '__main__':
  print(sys.path)
  fun2()
  fun3()
  fun1()

我們直接點pycharm的執行

結果如下:

 我們把結果的內容復制下來:

D:\ProgramFiles\Anaconda3\python.exe D:/Projects/python/vscode/python-module/src/main/package2/moduletest3.py
['D:\\Projects\\python\\vscode\\python-module\\src\\main\\package2', 
'D:\\Projects\\python\\vscode\\python-module', 
'D:\\ProgramFiles\\JetBrains\\PyCharm 2020.1\\plugins\\python\\helpers\\pycharm_display', 
'D:\\ProgramFiles\\Anaconda3\\python38.zip', 
'D:\\ProgramFiles\\Anaconda3\\DLLs', 
'D:\\ProgramFiles\\Anaconda3\\lib', 
'D:\\ProgramFiles\\Anaconda3', 
'D:\\ProgramFiles\\Anaconda3\\lib\\site-packages', 
'D:\\ProgramFiles\\Anaconda3\\lib\\site-packages\\win32', 
'D:\\ProgramFiles\\Anaconda3\\lib\\site-packages\\win32\\lib', 
'D:\\ProgramFiles\\Anaconda3\\lib\\site-packages\\Pythonwin', 
'D:\\ProgramFiles\\JetBrains\\PyCharm 2020.1\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
我是來自 module2
我是來自 module3
我是來自 module1

Process finished with exit code 0

我的天,sys.path 中包含

'D:\\Projects\\python\\vscode\\python-module\\src\\main\\package2', 
'D:\\Projects\\python\\vscode\\python-module'

所以嘛,不要抬杠!!!

四、設置全局變量 -- 作用域是一直存在

1、添加環境變量 

PYTHONPATH=D:\Projects\python\vscode\python-module
方法: 
對於Windows,右鍵我的電腦 --> 屬性 --> 高級系統設置 --> 環境變量 --> 既可以添加用戶環境變量,也可以添加系統環境變量 -->
 新建 --> 添加變量名:PYTHONPATH,添加變量值:D:\Projects\python\vscode\python-module --> 確定

 2、按照慣例,我們測試一下sys.path

moduletest4.py如下

import sys
# 測試第四種:設置全局變量 -- 作用域是一直存在
# 對於Windows,右鍵我的電腦 --> 屬性 --> 高級系統設置 --> 環境變量 --> 既可以添加用戶環境變量,也可以添加系統環境變量 -->
# 新建 --> 添加變量名:PYTHONPATH,添加變量值:D:\Projects\python\vscode\python-module --> 確定
# python moduletest4.py 


if __name__ == '__main__':
  print(sys.path)

打開新的cmd(老的還是老配置,只有新的),切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

sys.path 中包含

'D:\\Projects\\python\\vscode\\python-module\\src\\main\\package2', 
'D:\\Projects\\python\\vscode\\python-module'

3、我們直接引入模塊module1.py和module2.py和module3.py

moduletest4.py如下

import sys
# 測試第四種:設置全局變量 -- 作用域是一直存在
# 對於Windows,右鍵我的電腦 --> 屬性 --> 高級系統設置 --> 環境變量 --> 既可以添加用戶環境變量,也可以添加系統環境變量 -->
# 新建 --> 添加變量名:PYTHONPATH,添加變量值:D:\Projects\python\vscode\python-module --> 確定
# python moduletest4.py 


from src.main.package2.module2 import fun2
from src.main.package2.package3.module3 import fun3
from src.main.package1.module1 import fun1


if __name__ == '__main__':
  print(sys.path)
  fun2()
  fun3()
  fun1()

打開新的cmd,切換到該文件所在目錄,執行 

python moduletest1.py

結果如下所示:

 

 

 五、把文件添加到默認路徑中 -- 還是算了吧,一般都不用這種的。

除非是針對python的封裝等,比如Anaconda等。請自行解決。

當你導入一個模塊,Python 解析器對模塊位置的搜索順序是:

  • 1、當前目錄
  • 2、如果不在當前目錄,Python 則搜索在 shell 變量 PYTHONPATH 下的每個目錄。
  • 3、如果都找不到,Python會察看默認路徑。UNIX下,默認路徑一般為/usr/local/lib/python/。

模塊搜索路徑存儲在 system 模塊的 sys.path 變量中。變量里包含當前目錄,PYTHONPATH和由安裝過程決定的默認目錄。

 

 總結:

1、按照自動搜索方法,會先搜索當前目錄,但是該方法的缺點是不能識別上級目錄的模塊,並且作用域只是該py文件

2、自己在py中添加環境變量,會識別本目錄,以及從添加目錄開始的模塊,但是該方法的缺點是每個py文件都要添加環境變量,並且作用域只是該py文件

3、打開cmd,設置本窗口的變量。 set PYTHONPATH=D:\\Projects\\python\\vscode\\python-module,可以通過 echo %PYTHONPATH% 查看。這么設置的話,作用域是本窗口。

4、設置全局的環境變量。作用域一直存在。我們不需要了在刪除之。

5、把文件添加到默認路徑中。

 

參考:Python 模塊 - https://www.runoob.com/python/python-modules.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM