您好,登錄后才能下訂單哦!
這篇文章主要介紹“python模塊引入問題如何解決”的相關(guān)知識,小編通過實(shí)際案例向大家展示操作過程,操作方法簡單快捷,實(shí)用性強(qiáng),希望這篇“python模塊引入問題如何解決”文章能幫助大家解決問題。
使用pycharm等編輯器run/debug運(yùn)行python腳本時,編輯器會通過本地python命令全路徑執(zhí)行腳本,例如
D:\DevelopTools\Python\python.exe D:/Codes/一長串路徑/bbss_nature_python/demo/test_no_param_in.py
并且會在python系統(tǒng)環(huán)境命令路徑prepend即append first拼接啟動腳本的絕對目錄路徑和腳本依賴的絕對目錄路徑,例如
print ("sys.path") ['D:\\Codes\\一長串路徑\\bbss_nature_python\\demo', 'D:\\Codes\\一長串路徑\\bbss_nature_python', ...]
這是由于pycharm編輯器run/debug配置中自動定義了全路徑工作目錄、全路徑啟動腳本、環(huán)境命令拼接等,如下圖
例1
D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust>python bbss_nature_python/demo/test_no_param_in.py
在以上工作目錄,使用相對路徑運(yùn)行python腳本,報(bào)錯如下(絕對路徑也是同樣的報(bào)錯)
Traceback (most recent call last):
File "D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust\bbss_nature_python\demo\test_no_param_in.py", line 17, in <module>
from common_code import ScriptReturnClz, _object2json_str
ModuleNotFoundError: No module named 'common_code'
例2
D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust>python bbss_nature_python/demo/test_no_param_in.py
在以上工作目錄,使用相對路徑運(yùn)行python腳本,報(bào)錯如下(絕對路徑也是同樣的報(bào)錯)
Traceback (most recent call last):
File "D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust\bbss_nature_python\demo\test_no_param_in.py", line 18, in <module>
from ..common_code import ScriptReturnClz, _object2json_str
ImportError: attempted relative import with no known parent package
Python在引用庫文件時,會自動從python安裝目錄的Lib子目錄等目錄查找依賴,默認(rèn)查找路徑可以通過命令print(sys.path)查看
print ("sys.path") ['D:\\Codes\\cust\\rycust\\bbss_nature_cust_2021-2030\\bbss_nature_cust\\bbss_nature_python\\demo', 'D:\\DevelopTools\\Python\\python310.zip', 'D:\\DevelopTools\\Python\\DLLs', 'D:\\DevelopTools\\Python\\lib', 'D:\\DevelopTools\\Pyt hon', 'D:\\DevelopTools\\Python\\lib\\site-packages']
可以看到,python命令執(zhí)行一個python腳本前,會在sys.path數(shù)組第一位拼接啟動腳本的目錄絕對路徑
測試用例目錄文件樹形圖如下
在引用自定義模塊時,如果模塊和當(dāng)前腳本在同一目錄下,引入的時候,有以下幾種方式:
1.直接模塊名引入√【不建議】
如
from test_with_param_in import _print_json_param
此時,pycharm編輯器會告警,但python、pycharm運(yùn)行都是正常的
可以選擇忽略告警(告警右鍵選擇ignore)
2.包名.模塊名引入√【推薦,參見后文最佳方案】
如
from demo.test_with_param_in import _print_json_param
此時,pycharm編輯器不會告警,但python運(yùn)行會報(bào)錯
Traceback (most recent call last):
File "D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust\bbss_nature_python\demo\test_no_param_in.py", line 16, in <module>
from demo.test_with_param_in import _print_json_param
ModuleNotFoundError: No module named 'demo'
此時需要引入缺少的模塊所在的目錄的絕對路徑,如下
current_script_dir = os.path.split(os.path.realpath(__file__))[0] current_script_dir_parent = os.path.split(current_script_dir)[0] sys.path.insert(0, current_script_dir_parent)
3..模塊名引入×【不可行】
如
from .test_with_param_in import _print_json_param
此時,pycharm編輯器不會告警,但python運(yùn)行會報(bào)錯
Traceback (most recent call last):
File "D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust\bbss_nature_python\demo\test_no_param_in.py", line 16, in <module>
from .test_with_param_in import _print_json_param
ImportError: attempted relative import with no known parent package
無解決方案
如果模塊和當(dāng)前腳本不在同一目錄下,必須指定模塊路徑,可以在當(dāng)前腳本中import sys然后
通過sys.path.append(‘待引入的模塊路徑’)或者sys.path.insert(0,‘待引入的模塊路徑’)拼接的方式加入python系統(tǒng)命令路徑,建議insert
待引入的模塊路徑,應(yīng)該使用絕對(abs)路徑,對于相對路徑,python會直接拼接工作目錄+相對路徑生成絕對路徑,拼接后的絕對路徑是錯誤的(除非工作目錄本身就是啟動腳本的目錄)
腳本內(nèi)容:
# 當(dāng)前腳本abs目錄 current_script_dir = os.path.split(os.path.realpath(__file__))[0] # 當(dāng)前腳本目錄的上級abs目錄(對于本測試用例即為待引入模塊的abs目錄) current_script_dir_parent = os.path.split(current_script_dir)[0] # 待引入模塊common_code的abs目錄加入系統(tǒng)環(huán)境命令路徑數(shù)組 sys.path.insert(0, current_script_dir_parent) print("print (\"sys.path\")") print(sys.path) # 引入自定義模塊common_code【注意,代碼中必須先添加路徑之后才能引入】 from common_code import ScriptReturnClz, _object2json_str
命令:
D:\Codes\cust\rycust\bbss_nature_cust_2021-2030\bbss_nature_cust>python bbss_nature_python/demo/test_no_param_in.py
運(yùn)行結(jié)果:
print ("sys.path")
['D:\\Codes\\cust\\rycust\\bbss_nature_cust_2021-2030\\bbss_nature_cust\\bbss_nature_python', 'D:\\Codes\\cust\\rycust\\bbss_nature_cust_2021-2030\\bbss_nature_cust\\bbss_nature_python\\demo', 'D:\\DevelopTools\\Python\\python310.zi
p', 'D:\\DevelopTools\\Python\\DLLs', 'D:\\DevelopTools\\Python\\lib', 'D:\\DevelopTools\\Python', 'D:\\DevelopTools\\Python\\lib\\site-packages']
當(dāng)待引入的模塊和當(dāng)前腳本在不同目錄下時,需要在環(huán)境變量中加入待引入模塊目錄的絕對路徑,每個類似的啟動腳本(即python命令執(zhí)行的腳本)都需要編寫很多類似的模板代碼,而且由于依賴的傳遞性,可能無法簡單地遍歷出所有的自定義依賴模塊
復(fù)雜依賴的python腳本,尤其是系統(tǒng)級規(guī)?;膒ython工程,通常使用pycharm等IDE編寫。IDE會創(chuàng)建python工程,并且以工程目錄為工作目錄,在編寫py腳本時,從工作目錄開始查找自定義模塊,自動補(bǔ)齊工作目錄下的相對路徑。另外,在打包python工程時,也是從工程目錄開始。因此,使用IDE的默認(rèn)的補(bǔ)全模塊路徑的依賴引入方式是最優(yōu)選擇
不同于java微服務(wù)子工程之間的依賴引用,python沒有子工程概念,只有一個完整的未拆分的工程。如果兩個工程之間有模塊依賴關(guān)系,則需要同時部署兩個工程,并使用絕對路徑引入另一個工程的工程目錄,然后從工程目錄開始引入所需模塊。對于常用的自定義的基礎(chǔ)依賴,也可以打包發(fā)布到公有源或私有源,直接install引入模塊。從工程角度考慮,需要區(qū)分模塊的命名空間,應(yīng)采用和java包名類似的方式,以組織或個人的標(biāo)識創(chuàng)建模塊總包
鑒于IDE的依賴引入方式,只要將python工程的工程目錄加入sys.path,則工程內(nèi)的任何一個pycharm可成功運(yùn)行的啟動腳本都可以用python命令成功運(yùn)行
怎樣可以方便地找到一個python工程的工程目錄?這取決于一個工程有多少啟動腳本,以及每個啟動腳本的位置
如果一個python工程只有一個啟動腳本,比如一個python文件服務(wù)器,那么這個腳本應(yīng)該直接放在工程一級目錄下(如下圖中工程目錄為D:\tmp\python,start.py為啟動腳本),這樣可以順利找到當(dāng)前工程中的所有自定義依賴,這是因?yàn)閱幽_本路徑自動拼接環(huán)境變量
如果一個python工程有多個啟動腳本,并且不是都在工程目錄下,比如一個python計(jì)算工具包,那么每一個啟動腳本的全局代碼塊都需要添加工程目錄,舉例如下
# 當(dāng)前腳本abs目錄 current_script_dir = os.path.split(os.path.realpath(__file__))[0] # 當(dāng)前腳本目錄的上級abs目錄(對于本測試用例即為python工程abs目錄,如果不是,可繼續(xù)上溯) current_script_dir_parent = os.path.split(current_script_dir)[0] # python工程路徑 python_project_dir = current_script_dir_parent if sys.path[0] != python_project_dir: sys.path.insert(0, python_project_dir) print("添加工程目錄:" + python_project_dir) print("print (\"sys.path\")") print(sys.path)
關(guān)于“python模塊引入問題如何解決”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點(diǎn)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。