Python模块之间的相互引用问题
在某次運行過程中出現了如下兩個報錯:
報錯1: ModuleNotFoundError: No module named '__main__.src_test1'; '__main__' is not a package
報錯2: ImportError: attempted relative import with no known parent package
于是基于這兩個報錯探究了一下python3中的模塊相互引用的問題,下面來逐個解析,請耐心看完。
好的,我們先來構造第一個錯:
測試代碼結構如下:
|--- test_main.py |--- src|--- __init__.py |--- src_test1.py|--- src_test2.pysrc_test2.py 代碼
class Test2(object):def foo(self):print('I am foo')src_test1.py代碼,引用Test2模塊
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' from .src_test2 import Test2def fun1():t2 = Test2()t2.foo() if __name__ == "__main__":fun1()此時運行 src_test1.py 報錯No module named '__main__.src_test1'; '__main__' is not a package
問題原因:
主要在于引用src_test2模塊的時候,用的是相對路徑".",在import語法中翻譯成"./",也就是當前目錄下,按這樣理解也沒有問題,那為什么報錯呢?
從 PEP 328 中,我們找到了關于 the relative imports(相對引用)的介紹
通俗一點意思就是,你程序入口運行的那個模塊,就默認為主模塊,他的name就是‘main’,然后會將本模塊import中的點(.)替換成__main__,那么 .src_test2就變成了__main__.src_test2,所以當然找不到這個模塊了。
解決方法:
因此,建議的做法是在 src同層級目錄創建 引用模塊 test_main.py(為什么不在src目錄下創建,待會下一個報錯再講),并引用src_test1模塊,代碼如下:
from src.src_test1 import fun1if __name__ == "__main__":fun1()test_src 代碼:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' from src_test1 import fun1if __name__ == "__main__":fun1()執行報錯:ImportError: attempted relative import with no known parent package
問題原因:
當執行test_src時,按上文理解,此時執行文件所在的目錄為根目錄,那么引用test1的時候,需要注意的是,此時test1的name屬性不再是src.src_test1,因為程序感知不到src的存在,此時他的絕對路徑是 src_test1,此時再次引用相對路徑查找的test2,同樣的步驟,需要先找到父節點,而此時他自己就是根節點了,已經沒有父節點了,因此報錯“no known parent package”。
解決方法:
此時為了避免父節點產生矛盾,因此將test1中的引入去掉相對引用即可
from .src_test2 import Test2 --> from src_test2 import Test2繼續深入:
那使用相對路徑和絕對路徑,編譯器是怎么找到這個模塊的呢?
執行import的時候,存在一個引入的順序,即優先查找執行目錄下有沒有此文件,如沒有,再查找lib庫下,如還沒有,再查找sys.path中的路徑,如再沒有,報錯。
所以不管是當前目錄,還是 sys.path中的目錄,都可以查到 src_test2這個模塊,就可以編譯成功。
號外:
解決完上述問題后,不管我們用哪種方式,我們調試代碼時,都是單個文件調試,但此時根目錄就不對了,import方式又要改動,執行起來很麻煩,所以這里推薦另一種方式(有更好的方式歡迎留言),使用sys.path.append()的方法
import sys,os sys.path.append(os.getcwd()) from src.src_test2 import Test2使用append的方式,將程序文件根目錄放進了sys.path中,然后再引用絕對路徑,這樣的方式,不管使用上文中的第一或第二執行方式都可以調用,也可以單獨編譯test1文件,不用修改import路徑,也是相對安全的方式。但是缺點就是,如果你修改了某一個包名,需要將所有引用地方都修改一下,工作量大,所以因地制宜。
綜上,詳細講解了相對路徑和絕對路徑的引用方法,現在你應該對import導入的問題有了清晰的理解吧
總結
以上是生活随笔為你收集整理的Python模块之间的相互引用问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何创建你的第一个Python元类?
- 下一篇: 知道Python中的字符串是什么吗?