簡體   English   中英

哪個是處理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的原因很多:

  • 如果您的模塊直接依賴於模塊,請讓錯誤發生。 如果依賴項的安裝很簡單,某些庫會使用有用的錯誤消息重新引發該錯誤。
  • 如果您的模塊嘗試使用相同的API將較慢的庫替換為較快的庫,則沒有理由在屏幕上打印任何內容。
  • 如果您的模塊期望某個特定的庫存在,但是您可以找到的唯一庫明顯要慢得多,那么警告可能會很有用,以使開發人員知道您的模塊仍然可以運行,但運行得不那么快。

現在,對於您的其他問題:

然后,導入最強大的程序包(例如此處的lxml)變得沒有意義,我們可以直接導入功能最差的程序包,並節省很多代碼。

lxml.etreeElementTreecElementTree的特定情況下,所有三個都實現相同的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM