[英]Raise a custom exception on import
簡短的問題:我有一個帶有對象的模塊。 如果有人從我的模塊導入一個對象,我的指定異常被引發,我該怎么做?
我想做什么:我寫一個架構框架。 輸出類依賴於jinja2
外部庫。 我希望框架也可以在沒有這種依賴性的情況下使用。 在包的__init__.py
我編寫了我的類RenderLaTeX
條件導入(如果 jinja2 可用,則導入該類,否則不導入)。
這種方法的問題是我有一些代碼使用了這個類RenderLaTeX
,但是當我在新的設置上運行它時,我收到一個錯誤,比如Import error: no class RenderLaTeX could be imported from output
。 在我記得必須事先安裝jinja2
之前,這個錯誤是非常意外和無法理解的。
我想到了這個解決方案:如果類不可用, __init__.py
可以創建一個具有此名稱的字符串。 如果用戶嘗試使用通常的類構造函數實例化這個對象,他們會得到一個更有意義的錯誤。 不幸的是,簡單的導入
from output import RenderLaTeX
在這種情況下不會引發錯誤。
您有什么建議,希望能結合優點和缺點的描述?
重要 UPD:我將我的類打包在模塊中,並通過__init__.py
將它們導入模塊,以便我導入“from lena.flow import ReadROOTFile”,而不是“from lena.flow.read_root_file import ReadROOTFile”。
當 Python 導入一個模塊時,您要從中導入的文件中的所有代碼都會被執行。
如果您的RenderLaTeX
類因此被放置到一個單獨的文件中,您可以自由添加邏輯,如果缺少所需的依賴項,將阻止它被導入(或運行)。
例如:
try:
import somethingidonthave
except ImportError:
raise Exception('You need this module!')
class RenderLaTeX(object):
pass
您還可以將您想要的任何自定義消息添加到異常中以更好地描述錯誤。 這應該適用於 Python2 和 Python3。
經過一年的思考,解決方案出現了。
首先,我認為覆蓋異常類型是毫無意義的。 唯一的好方法是為丟失的導入添加有用的消息。
其次,我認為語法
from framework.renderers import MyRenderer
真的比
from framework.renderers.my_renderer import MyRenderer
因為它隱藏了實現細節並且需要更少的用戶代碼(我更新了我的問題以反映這一點)。 為了使前一種語法起作用,我必須在模塊的__init__.py
中導入MyRenderer 。
現在,在my_renderer.py
我通常會導入第三方包
import huge_specific_library
在標題中。 PEP 8需要此語法。 然而,這會使整個framework.renderers模塊依賴於huge_specific_library 。
解決方案是違反 PEP 8 並在類本身中導入庫:
class MyRenderer():
def __init__(self):
import huge_specific_library
# ... use that...
如果這很重要,您可以在這里捕獲異常,更改其消息等。還有另一個好處:存在如何減少導入時間的指南,他們提出了這個解決方案(我很久以前讀過它們但忘記了)。 大型模塊需要一些時間來加載。 如果您遵循 PEP 8 樣式指南(我仍然認為您通常應該這樣做),這可能會導致大量延遲,只是為了將所有導入到您的程序中,而還沒有做任何有用的事情。
唯一的警告是:如果您在__init__ 中導入庫,您還應該將其導入到使用它的其他類方法中,否則它將在那里不可見。
對於那些仍然懷疑的人,我必須補充一點,由於 Python 導入已被緩存,因此如果您使用 import 的方法調用頻率不高,這不會影響性能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.