ModuleNotFoundError: No module named xxx 的原因和解決辦法(附帶新大陸)

#PS:要轉載請註明出處,本人版權所有

#PS:這個只是 《 我自己 》理解,如果和你的

#原則相沖突,請諒解,勿噴

ModuleNotFoundError: No module named ‘xxx’ 分析

這個問題只要是用過python的人,一般或多或少都會遇到過這個問題,這個問題其實很明確,就是你import的module找不到。
關於爲啥找不到的原因,倒是有很多花裏胡哨原因。

Python module的搜索路徑

python的module搜索路徑,其實是編譯python的時候就有相關的默認配置的。例如:

python -m sysconfig

在這裏插入圖片描述
這裏面就包含了相應的搜索路徑。但是我們執行如下命令看真實的搜索路徑,就會發現一些奇怪的東西。

python3 -c “import sys;print(sys.path)”

在這裏插入圖片描述

其實這裏可以看出多了一些不常見的搜索目錄,其實出了我們常見的site-packages外,python還有其他builtin 和一些獨立的自帶的模塊。site-packages在約定中,是用來存放第三方庫的,也就是你pip install安裝的module.
這裏有個重要的目錄是/usr/lib/python3.6/lib-dynload/,裏面的so是python 自帶模塊的底層實現,比如ctype 對應的實現是 _ctype.
在這裏插入圖片描述
上面sys.path包含的路徑,就是python import 模塊時的全部搜索路徑了。當然,還包含一個當前路徑,也就是你執行python命令的路徑,也會被默認搜索。

此外,通過環境變量PYTHONPATH也可以向sys.path添加值。

正常情況下,我們就可以通過在這些目錄裏面放置我們的模塊,然後在python裏面import即可。

ModuleNotFoundError: No module named ‘xxx’ 可能原因和解決方案

s1

原因:sys.path 所包含的所有目錄中,確實無對應的xxx模塊。
解決方法:這個時候,通過pip install安裝即可解決。

s2

原因:sys.path 所包含的所有目錄中,有對應的xxx模塊,但是有多個地方都存在(可能是同樣的版本,可能是不一樣的版本)。
解決方法:所有的目錄中,只保留一個xxx模塊即可,其他的都uninstall了。(小提示:這裏推薦使用虛擬環境,這樣就很少出現這種情況,出現這種情況的本質原因還是一個系統配置了太多的python版本)

s3 (新大陸)

這種情況也是我最近遇到的新坑。具體表現是sys.path目錄中有xxx模塊,而且還有且只有一個。根據我們上文的s1,s2情況來看,這就應該解決的問題了呀,可是並沒有。這就讓我很懵逼。

情況復現:我手動編譯了一個python3,需要使用python c interface功能。我同時生成了debug和release的python3的庫。在我嘗試import numpy的時候,release的庫一直ok,但是debug的python庫一直報找不到numpy的庫。(我確定numpy在sys.path中,而且只有一個)

經過我大量的尋找,在如下的一個鏈接(https://bugs.python.org/issue36716)裏面,找到了答案。
在這裏插入圖片描述
原來python 的debug和release版本,import 的時候,一些庫的命名上面是有區別的。
我們分別在linux和win下執行如下:

import importlib.machinery
print(importlib.machinery.all_suffixes())

linux:
在這裏插入圖片描述
windows:
release:
在這裏插入圖片描述
debug:
在這裏插入圖片描述

可以看到,這裏的.pyd(類似windows dll)和.so(類似linux so)分別是不通平臺下,python import 需要的庫的後綴。

同時我們也可以看到,同一平臺下,release 和 debug版本的python import的時候,需要的module名字可能有些詫異,最直白的就是多了_d。
注意:windows-debug圖中畫紅框部分,是由於我改了python的源碼,它纔會認識不帶_d的module。哪怕這個module命名不帶_d,但是它必須是debug版本的module纔行,換句話說,僅僅是命名上的區別。如果你弄一個release的庫,我這個python的debug版本依然不會import成功。改原因的原因也很苦逼,就是通過編譯生成的debug module,它不會自動的給你加上_d,坑爹,如果這種模塊多,需要你自己重命名的module太多了,於是,直接該源碼纔是很爽的方法。

解決方法也很簡單的:直接編譯一個debug版本的xxx模塊即可。同時修改生成的module庫,加上_d即可解決。

原因也很簡單就是庫的名字沒有對上,導致找不到。

一般來說,s3這種情況大家都不會碰見的,除非和我一樣,用python c interface的時候,在debug模式下使用,就可能會出現這種情況。找起答案來,也比較麻煩。

未完待續(以後遇到新的再補充)

#PS:請尊重原創,不喜勿噴

#PS:要轉載請註明出處,本人版權所有.

有問題請留言,看到後我會第一時間回覆

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章