找出`ImportError`引发时真正出了什么问题

4 投票
3 回答
12842 浏览
提问于 2025-04-16 12:26

以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 个回答

-3

我发现一件让人很沮丧的事情就是,当你试图处理导入错误时,实际上你很快就会陷入一个复杂的麻烦中。

记住这一点。

绝对不要去处理导入错误。manage.py的例子并不是一个好的做法。

不要这样做。

导入错误应该是非常非常少见的。

1

处理那些你不想让错误信息继续传播,但又想让用户知道出错了的情况,最简单的方法就是在你打印的任何消息中,始终包含原始错误的详细信息:

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()将模块的位置和执行分开,但简单地包含原始错误信息就足以避免最麻烦的情况。

5

基本上,问题在于你的错误信息不准确——导入失败的原因有很多,不仅仅是路径错误。ImportError 只是意味着“你无法使用这个模块,查看错误追踪信息来找出原因”,你只是急于下结论。

如果你想显示“找不到文件”,那么你应该先去找这个文件。imp.find_module 就是用来做这件事的。

撰写回答