缺失模块的导入时更友好的错误信息

5 投票
4 回答
5133 浏览
提问于 2025-04-15 15:20

我想在用户尝试运行一个Python脚本时,如果这个脚本要导入的模块没有安装,就给出一些更友好的错误提示。这包括打印出如何安装缺失模块的说明。

一种方法是把导入模块的代码放在一个try..catch块里,但这样看起来有点麻烦,因为这会把简单的代码变成

import some_module

变成这样

try:
  import some_module
except ImportError, e:
  handle_error(e)

而且每个文件都需要加上这个代码。此外,ImportError似乎没有地方存储缺失模块的名字(除了错误信息本身),所以如果你需要知道缺失的模块名(就像我需要的那样),你就得在每个导入语句周围都加一个单独的try..catch。解析模块名也不是个好办法,因为ImportError的错误信息可能会随着Python版本的不同而变化,或者根据用户的语言环境不同而变化。

我想我可以用sys.excepthook来捕获所有异常,并把除了ImportError以外的异常都传递出去。或者说,是否有可能定义一些像这样

safe_import some_module

的东西,让它按照我想要的方式工作呢?

有没有人知道解决这个问题的现成方法?

4 个回答

3

你不需要为每一个导入都捕获ImportError(导入错误)。你可以在脚本的入口点使用一个全局的try..except块。

你可以通过ImportError实例的message属性获取缺失模块的名称。

举个例子,如果你的脚本入口文件是main.py:

if __name__ == '__main__':
    try:
        import module1
        import module2

        module1.main()
     except ImportError as error:
        print "You don't have module {0} installed".format(error.message[16:])

不要在try..except块外导入任何东西。这将涵盖module1、module2以及它们导入的所有模块,依此类推。

正如你所说的,你可以定义自己的import_safe函数:

def import_safe(module):
    try:
        return __import__(module)
    except ImportError as error:
        print "You don't have module {0} installed".format(error.message[16:])

然后你可以使用这个函数:

sys = import_safe('sys')
gtk = import_safe('gkt')

在我看来,第一个策略更好。第二种方法会让你的代码难以阅读,并且会改变语言的一个重要部分。

6

你可以把这段代码放在一个总是会被执行的地方,比如说在site.py或者sitecustomize.py文件里:

import __builtin__

realimport = __builtin__.__import__

def myimport(modname, *a):
  try:
    return realimport(modname, *a)
  except ImportError, e:
    print "Oops, couldn't import %s (%s)" % (modname, e)
    print "Here: add nice directions and whatever else"
    raise

__builtin__.__import__ = myimport

想了解更多关于__import__的内容,可以查看它的文档,链接在这里

2

我会在这个包里添加一些额外的模块,当你导入它们的时候,它们会先打印出一些更有帮助的信息,然后再抛出一个普通的导入错误(ImportError)。当真正的模块安装好后,你的这些模块就会被隐藏起来(确保你把它们所在的目录放在 sys.path 的最后)。

撰写回答