找出`ImportError`引发时真正出了什么问题
以Django为例,在 manage.py
文件中:
try:
import settings
except ImportError:
sys.stderr.write("Error: Can't find the file 'settings.py'...")
看起来没问题,但如果 settings
里引入了一个叫 non_existant_lib_foo
的库,结果会怎样呢?
那你就得花时间去查找所有可能出错的地方,比如 PATH
等等。
当然,你可以用 except ImportError as e:
来捕捉错误,然后打印出实际的错误信息,但如果你只想捕捉特定的错误,并给出一些很好的建议,比如上面提到的那样呢?
这时候你就只能用正则表达式,或者最好的情况是猜测哪个“正确”的模块引入失败,然后显示相关的错误信息。
有没有更好的方法来处理这个问题呢?
3 个回答
我发现一件让人很沮丧的事情就是,当你试图处理导入错误时,实际上你很快就会陷入一个复杂的麻烦中。
记住这一点。
绝对不要去处理导入错误。manage.py
的例子并不是一个好的做法。
不要这样做。
导入错误应该是非常非常少见的。
处理那些你不想让错误信息继续传播,但又想让用户知道出错了的情况,最简单的方法就是在你打印的任何消息中,始终包含原始错误的详细信息:
try:
import settings
except ImportError as exc:
sys.stderr.write("Error: failed to import settings module ({})".format(exc))
这样一来,在常见的情况下(比如用户把设置文件放错地方,或者配置出错导致sys.path
不对),你就能得到清晰的提示,而不会完全遮蔽在执行settings
模块时出现的其他导入错误。
更好的做法是,如果你使用了日志模块,可以把完整的错误信息(包括错误追踪)记录为debug()
或info()
的日志事件。
还有其他选择,比如做一个子字符串搜索if 'settings' not in str(exc): raise
,或者通过使用imp.find_module()
将模块的位置和执行分开,但简单地包含原始错误信息就足以避免最麻烦的情况。
基本上,问题在于你的错误信息不准确——导入失败的原因有很多,不仅仅是路径错误。ImportError
只是意味着“你无法使用这个模块,查看错误追踪信息来找出原因”,你只是急于下结论。
如果你想显示“找不到文件”,那么你应该先去找这个文件。imp.find_module
就是用来做这件事的。