![](/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.