
作者:豌豆花下貓
來(lái)源:Python貓
在寫 python 項(xiàng)目的時(shí)候,我們可能經(jīng)常會(huì)遇到導(dǎo)入模塊失敗的錯(cuò)誤:ImportError: No module named 'xxx'或者M(jìn)oduleNotFoundError: No module named 'xxx'。
導(dǎo)入失敗問(wèn)題,通常分為兩種:一種是導(dǎo)入自己寫的模塊(即以 .py 為后綴的文件),另一種是導(dǎo)入三方庫(kù)。本文主要討論第二種情況,今后有機(jī)會(huì),我們?cè)僭敿?xì)討論其它的相關(guān)話題。
解決導(dǎo)入 Python 庫(kù)失敗的問(wèn)題,其實(shí)關(guān)鍵是在運(yùn)行環(huán)境中裝上缺失的庫(kù)(注意是否是虛擬環(huán)境),或者使用恰當(dāng)?shù)奶娲桨浮_@個(gè)問(wèn)題又分為三種情況:
一、單個(gè)模塊中缺失的庫(kù)
在編寫代碼的時(shí)候,如果我們需要使用某個(gè)三方庫(kù)(如 requests),但不確定實(shí)際運(yùn)行的環(huán)境是否裝了它,那么可以這樣:
try: import requests except ImportError: import os os.system('pip install requests') import requests
這樣寫的效果是,如果找不到 requests 庫(kù),就先安裝,再導(dǎo)入。在某些開(kāi)源項(xiàng)目中,我們可能還會(huì)看到如下的寫法(以 json 為例):
try: import simplejson as json except ImportError: import json
這樣寫的效果是,優(yōu)先導(dǎo)入三方庫(kù) simplejson,如果找不到,那就使用內(nèi)置的標(biāo)準(zhǔn)庫(kù) json。
這種寫法的好處是不需要導(dǎo)入額外的庫(kù),但它有個(gè)缺點(diǎn),即需要保證那兩個(gè)庫(kù)在使用上是兼容的,如果在標(biāo)準(zhǔn)庫(kù)中找不到替代的庫(kù),那就不可行了。
如果真找不到兼容的標(biāo)準(zhǔn)庫(kù),也可以自己寫一個(gè)模塊(如 my_json.py),實(shí)現(xiàn)想要的東西,然后在 except 語(yǔ)句中導(dǎo)入它。
try: import simplejson as json except ImportError: import my_json as json
二、整個(gè)項(xiàng)目中缺失的庫(kù)
以上的思路是針對(duì)開(kāi)發(fā)中的項(xiàng)目,但是它有幾個(gè)不足:1、在代碼中對(duì)每個(gè)可能缺失的三方庫(kù)都 pip install,并不可取;2、某個(gè)三方庫(kù)無(wú)法被標(biāo)準(zhǔn)庫(kù)或自己手寫的庫(kù)替代,該怎么辦?3、已成型的項(xiàng)目,不允許做這些修改怎么辦?
所以這里的問(wèn)題是:有一個(gè)項(xiàng)目,想要部署到新的機(jī)器上,它涉及很多三方庫(kù),但是機(jī)器上都沒(méi)有預(yù)裝,該怎么辦?
對(duì)于一個(gè)合規(guī)的項(xiàng)目,按照約定,通常它會(huì)包含一個(gè)“requirements.txt ”文件,記錄了該項(xiàng)目的所有依賴庫(kù)及其所需的版本號(hào)。這是在項(xiàng)目發(fā)布前,使用命令pip freeze > requirements.txt 生成的。
使用命令pip install -r requirements.txt (在該文件所在目錄執(zhí)行,或在命令中寫全文件的路徑),就能自動(dòng)把所有的依賴庫(kù)給裝上。
但是,如果項(xiàng)目不合規(guī),或者由于其它倒霉的原因,我們沒(méi)有這樣的文件,又該如何是好?
一個(gè)笨方法就是,把項(xiàng)目跑起來(lái),等它出錯(cuò),遇到一個(gè)導(dǎo)庫(kù)失敗,就手動(dòng)裝一個(gè),然后再跑一遍項(xiàng)目,遇到導(dǎo)庫(kù)失敗就裝一下,如此循環(huán)……(此處省略 1 萬(wàn)句臟話)……
三、自動(dòng)導(dǎo)入任意缺失的庫(kù)
有沒(méi)有一種更好的可以自動(dòng)導(dǎo)入缺失的庫(kù)的方法呢?
在不修改原有的代碼的情況下,在不需要“requirements.txt”文件的情況下,有沒(méi)有辦法自動(dòng)導(dǎo)入所需要的庫(kù)呢?當(dāng)然有!先看看效果:
我們以 tornado 為例,第一步操作可看出,我們沒(méi)有裝過(guò) tornado,經(jīng)過(guò)第二步操作后,再次導(dǎo)入 tornado 時(shí),程序會(huì)幫我們自動(dòng)下載并安裝好 tornado,所以不再報(bào)錯(cuò)。
autoinstall 是我們手寫的模塊,代碼如下:
# 以下代碼在 python 3.6.1 版本驗(yàn)證通過(guò) import sys import os from importlib import import_module class AutoInstall(): _loaded = set() @classmethod def find_spec(cls, name, path, target=None): if path is None and name not in cls._loaded: cls._loaded.add(name) print("Installing", name) try: result = os.system('pip install {}'.format(name)) if result == 0: return import_module(name) except Exception as e: print("Failed", e) return None sys.meta_path.append(AutoInstall)
這段代碼中使用了sys.meta_path ,我們先打印一下,看看它是個(gè)什么東西?
Python 3 的 import 機(jī)制在查找過(guò)程中,大致順序如下:
其中要注意,sys.meta_path 在不同的 Python 版本中有所差異,比如它在 Python 2 與 Python 3 中差異很大;在較新的 Python 3 版本(3.4+)中,自定義的加載器需要實(shí)現(xiàn)find_spec方法,而早期的版本用的則是find_module。
以上代碼是一個(gè)自定義的類庫(kù)加載器 AutoInstall,可以實(shí)現(xiàn)自動(dòng)導(dǎo)入三方庫(kù)的目的。需要說(shuō)明一下,這種方法會(huì)“劫持”所有新導(dǎo)入的庫(kù),破壞原有的導(dǎo)入方式,因此也可能出現(xiàn)一些奇奇怪怪的問(wèn)題,敬請(qǐng)留意。
sys.meta_path 屬于 Python 探針的一種運(yùn)用。探針,即import hook,是 Python 幾乎不受人關(guān)注的機(jī)制,但它可以做很多事,例如加載網(wǎng)絡(luò)上的庫(kù)、在導(dǎo)入模塊時(shí)對(duì)模塊進(jìn)行修改、自動(dòng)安裝缺失庫(kù)、上傳審計(jì)信息、延遲加載等等。
限于篇幅,我們不再詳細(xì)展開(kāi)了。最后小結(jié)一下:
參考資料:
https://github.com/liuchang0812/slides/tree/master/pycon2015cn
http://blog.konghy.cn/2016/10/25/python-import-hook
https://docs.python.org/3/library/sys.html#sys.meta_path
想從事業(yè)務(wù)型數(shù)據(jù)分析師,您可以點(diǎn)擊>>>“數(shù)據(jù)分析師”了解課程詳情;
想從事大數(shù)據(jù)分析師,您可以點(diǎn)擊>>>“大數(shù)據(jù)就業(yè)”了解課程詳情;
想成為人工智能工程師,您可以點(diǎn)擊>>>“人工智能就業(yè)”了解課程詳情;
想了解Python數(shù)據(jù)分析,您可以點(diǎn)擊>>>“Python數(shù)據(jù)分析師”了解課程詳情;
數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼
若不方便掃碼,搜微信號(hào):CDAshujufenxi
SQL Server 中 CONVERT 函數(shù)的日期轉(zhuǎn)換:從基礎(chǔ)用法到實(shí)戰(zhàn)優(yōu)化 在 SQL Server 的數(shù)據(jù)處理中,日期格式轉(zhuǎn)換是高頻需求 —— 無(wú)論 ...
2025-09-18MySQL 大表拆分與關(guān)聯(lián)查詢效率:打破 “拆分必慢” 的認(rèn)知誤區(qū) 在 MySQL 數(shù)據(jù)庫(kù)管理中,“大表” 始終是性能優(yōu)化繞不開(kāi)的話題。 ...
2025-09-18CDA 數(shù)據(jù)分析師:表結(jié)構(gòu)數(shù)據(jù) “獲取 - 加工 - 使用” 全流程的賦能者 表結(jié)構(gòu)數(shù)據(jù)(如數(shù)據(jù)庫(kù)表、Excel 表、CSV 文件)是企業(yè)數(shù)字 ...
2025-09-18DSGE 模型中的 Et:理性預(yù)期算子的內(nèi)涵、作用與應(yīng)用解析 動(dòng)態(tài)隨機(jī)一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開(kāi)始提取前,需先判斷 TIF 文件的類型 —— ...
2025-09-17CDA 數(shù)據(jù)分析師:解鎖表結(jié)構(gòu)數(shù)據(jù)特征價(jià)值的專業(yè)核心 表結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 規(guī)范存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù),如數(shù)據(jù)庫(kù)表、Excel 表、 ...
2025-09-17Excel 導(dǎo)入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實(shí)戰(zhàn)應(yīng)用 在用 Python(如 pandas 庫(kù))處理 Excel 數(shù)據(jù)時(shí),“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗(yàn)與 t 檢驗(yàn):差異、適用場(chǎng)景與實(shí)踐應(yīng)用 在數(shù)據(jù)分析與統(tǒng)計(jì)學(xué)領(lǐng)域,假設(shè)檢驗(yàn)是驗(yàn)證研究假設(shè)、判斷數(shù)據(jù)差異是否 “ ...
2025-09-16CDA 數(shù)據(jù)分析師:掌控表格結(jié)構(gòu)數(shù)據(jù)全功能周期的專業(yè)操盤手 表格結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù),如 Excel 表、數(shù)據(jù) ...
2025-09-16MySQL 執(zhí)行計(jì)劃中 rows 數(shù)量的準(zhǔn)確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調(diào)優(yōu)中,EXPLAIN執(zhí)行計(jì)劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對(duì)象的 text 與 content:區(qū)別、場(chǎng)景與實(shí)踐指南 在 Python 進(jìn)行 HTTP 網(wǎng)絡(luò)請(qǐng)求開(kāi)發(fā)時(shí)(如使用requests ...
2025-09-15CDA 數(shù)據(jù)分析師:激活表格結(jié)構(gòu)數(shù)據(jù)價(jià)值的核心操盤手 表格結(jié)構(gòu)數(shù)據(jù)(如 Excel 表格、數(shù)據(jù)庫(kù)表)是企業(yè)最基礎(chǔ)、最核心的數(shù)據(jù)形態(tài) ...
2025-09-15Python HTTP 請(qǐng)求工具對(duì)比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請(qǐng)求(如接口調(diào)用、數(shù)據(jù)爬取 ...
2025-09-12解決 pd.read_csv 讀取長(zhǎng)浮點(diǎn)數(shù)據(jù)的科學(xué)計(jì)數(shù)法問(wèn)題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長(zhǎng)浮點(diǎn)數(shù)據(jù)時(shí)的科學(xué)計(jì)數(shù)法問(wèn)題 ...
2025-09-12CDA 數(shù)據(jù)分析師:業(yè)務(wù)數(shù)據(jù)分析步驟的落地者與價(jià)值優(yōu)化者 業(yè)務(wù)數(shù)據(jù)分析是企業(yè)解決日常運(yùn)營(yíng)問(wèn)題、提升執(zhí)行效率的核心手段,其價(jià)值 ...
2025-09-12用 SQL 驗(yàn)證業(yè)務(wù)邏輯:從規(guī)則拆解到數(shù)據(jù)把關(guān)的實(shí)戰(zhàn)指南 在業(yè)務(wù)系統(tǒng)落地過(guò)程中,“業(yè)務(wù)邏輯” 是連接 “需求設(shè)計(jì)” 與 “用戶體驗(yàn) ...
2025-09-11塔吉特百貨孕婦營(yíng)銷案例:數(shù)據(jù)驅(qū)動(dòng)下的精準(zhǔn)零售革命與啟示 在零售行業(yè) “流量紅利見(jiàn)頂” 的當(dāng)下,精準(zhǔn)營(yíng)銷成為企業(yè)突圍的核心方 ...
2025-09-11CDA 數(shù)據(jù)分析師與戰(zhàn)略 / 業(yè)務(wù)數(shù)據(jù)分析:概念辨析與協(xié)同價(jià)值 在數(shù)據(jù)驅(qū)動(dòng)決策的體系中,“戰(zhàn)略數(shù)據(jù)分析”“業(yè)務(wù)數(shù)據(jù)分析” 是企業(yè) ...
2025-09-11Excel 數(shù)據(jù)聚類分析:從操作實(shí)踐到業(yè)務(wù)價(jià)值挖掘 在數(shù)據(jù)分析場(chǎng)景中,聚類分析作為 “無(wú)監(jiān)督分組” 的核心工具,能從雜亂數(shù)據(jù)中挖 ...
2025-09-10統(tǒng)計(jì)模型的核心目的:從數(shù)據(jù)解讀到?jīng)Q策支撐的價(jià)值導(dǎo)向 統(tǒng)計(jì)模型作為數(shù)據(jù)分析的核心工具,并非簡(jiǎn)單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10