![](/img/trans.png)
[英]Three-way Python import chain results in ModuleNotFoundError or ImportError
[英]Which is the better way to handle ImportError - Raise error or import chain?
當在python中遇到ImportError時,我應該直接引發錯誤並要求用戶安裝它,還是應該使用導入鏈?
當我嘗試使用lxml包解析python中的xml文件時遇到了這個問題。
在其官方文檔中說:
如果您的代碼僅使用ElementTree API,並且不依賴於lxml.etree特有的任何功能,則還可以使用以下導入鏈(的任何部分)作為原始ElementTree的后備:
try:
from lxml import etree
print("running with lxml.etree")
except ImportError:
try:
import xml.etree.cElementTree as etree
print("running with cElementTree on Python 2.5+")
except ImportError:
...
在我看來,導入替代品不是一個好主意,因為:
如果您可以導入另一個庫作為替代庫,而該庫可能不具有lxml的所有方法,則所有腳本只能基於所有軟件包中的那些可用方法 。
然后,導入最強大的程序包(例如此處的lxml)變得沒有意義,我們可以直接導入功能最差的程序包,並節省很多代碼。 或者,如果以后要使用其他方法,則應直接引發ImportError。
但是,正如導入模塊時的錯誤處理中所回答的那樣,我發現這種方法似乎在python編程中經常使用:
根據在運行時導入的庫定義多級功能非常有用。
但是在我看來,只能通過不斷檢查是否已導入一個庫來實現多級功能,這會使整個代碼變得復雜而丑陋。
結果,我只是想知道為什么人們有時會使用這種結構,而不是直接引發錯誤?
首先要回答您的最后一個問題:
當在python中遇到ImportError時,我應該直接引發錯誤並要求用戶安裝它,還是應該使用導入鏈?
您可以處理ImportError
的原因很多:
現在,對於您的其他問題:
然后,導入最強大的程序包(例如此處的lxml)變得沒有意義,我們可以直接導入功能最差的程序包,並節省很多代碼。
在lxml.etree
, ElementTree
和cElementTree
的特定情況下,所有三個都實現相同的API。 他們是彼此的替代品。 ElementTree
是純Python的,將始終運行,但是cElementTree
通常存在並且速度更快。 lxml.etree
甚至更快,但它是一個外部模塊。
這樣想:
try:
import super_fast_widget as widget
except ImportError:
try:
import fast_widget as widget
except ImportError:
import slow_widget as widget
從代碼的角度來看,無論最終導入哪個庫, widget
都將始終工作相同,因此,如果您在乎性能,那么最好嘗試導入最快的實現,而退回到較慢的實現。
正確的是,如果允許使用回lxml
,則無法充分利用lxml
的所有功能。 這就是為什么使用lxml.etree
而不是lxml
。 它有意模仿其他兩個庫的API。
這是Django代碼庫中的類似示例:
# Use the C (faster) implementation if possible
try:
from yaml import CSafeLoader as SafeLoader
from yaml import CSafeDumper as SafeDumper
except ImportError:
from yaml import SafeLoader, SafeDumper
Python內部為許多內置模塊執行此操作。 有一個較慢的純Python版本,用作較快的C版本的后備。
但是,正如導入模塊時的錯誤處理中所回答的那樣,我發現這種方法似乎在python編程中經常使用:
您的lxml.etree
示例將較慢的庫替換為較快的庫。 鏈接的示例代碼為一堆相同的庫定義了一個通用的跨平台接口( getpass
)(提示您輸入密碼)。 作者處理ImportError
因為根據您的操作系統,這些單獨的模塊可能不存在。
您可以使用if platform.system() == 'Windows'
和類似的代碼替換某些try
塊,但是即使在單個OS中,也可能會有更好的模塊執行相同的任務,因此try
塊只是對其進行了簡化。 最后, getpass
仍會使用完全相同的API提示用戶輸入密碼,這是您真正關心的全部。
我通常使用導入鏈,因為輸出受到更多控制。
引發錯誤
Traceback (most recent call last):
File "core.py", line 1, in <module>
ImportError: <error description>
進口鏈
i Importing "lxml.etree"
x Error Importing "lxml.etree"
i Importing "xml.etree.cElementTree" on Python 2.5+
x Error Importing "xml.etree.cElementTree" on Python 2.5+
i Please Install "lxml.etree" or "xml.etree.xElementTree" on Python 2.5+
i Exit with code 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.